重载函数什么时候用virtual?
源码: source code - load_funtion.cpp
问题来源
template <typename VST> void traverse(VST visit); |
为什么这里不需要virtual??
// 单个T类型元素加1的类 |
为什么这里又需要virtual??
概念偏差
virtual 和我原先理解的重载函数不太相同。也就是vitual和重载函数不是同一个概念。
vitual为虚函数:基类的引用或者指针调用一个虚成员函数时会执行动态绑定。
重载函数:同一作用域内的几个函数名字相同但形参列表不同。
使用与不使用virtual
解释一下 virtual 和 override 搭配, 继承类中可对基类的虚函数重载struct Base { // 声明virtual后, 可被继承类override重载
virtual void print() {std::cout << "Base\n";}
};
struct Derived : Base { // 'override'可写可不写
void print() override {std::cout << "Derived\n";}
};
struct Base { |
关键问题: 上述两者什么差别????
运行测试一下:// 注释是使用virtual结果
Base b;
Derived d;
Base& br = b; // refer b, br的类型是Base&
Base& dr = d; // dr类型也是Base&
br.print(); // Base
dr.print(); // Derived
Base* pb = &b; // pointer to b, Base*
Base* pd = &d; // Base* as well
pb->print(); // Base
pd->print(); // Derived
b.Base::print(); // Base
d.Base::print(); // Base
使用vitual的运行结果:
Base |
不使用虚方法的运行结果:Base
Base
Base
Base
Base
Base
virtual版本, 基类的引用或者指针会在调用一个虚函数时候, 动态绑定对应的函数。
解决最初问题
为什么traverse函数不需要virtual
traverse函数,属于在同一作用域,形参列表不同的函数。重载的概念是函数重载的概念,并不是继承类之间的虚函数override概念。
为什么函数对象需要virtual重载操作符函数?
定义继承类Increase_two, override在基类中被声明成virtual的类, 实现元素加2// 函数对象用virtual声明operator()()
struct Increase {
// 重载()后, 对象可充当函数的功能
virtual void operator()(int* e) {(*e)++;}
};
struct Increase_two : Increase {
void operator()(int* e) override {(*e)+= 2;} // 元素+2;
};
测试函数, 以及prints结果如下:void f_increase() {
Increase a;
Increase_two b;
Increase& ra = a;
Increase& rb = b; // rb的类型为 Increase&
int e = 5; int* pe = &e;
ra.operator()(pe);
std::cout << "e = " << e << std::endl; // prints "e = 6"
int e2 = 5; int* pe2 = &e2;
rb.operator()(pe2); // 调用基类的引用时, 动态绑定到Increase_two中的方法
std::cout << "e2 = " << e2 << std::endl; // prints "e2 = 7"
}
对重载操作符声明virtual, 可以让继承类对他的重载操作符行为进行重载。当调用基类的引用或者指针时候, 在编译阶段就能绑定到继承类对应的重载函数版本。
静态成员声明定义使用
静态成员的特点
静态数据成员不属于任何类的一个对象。
类似于全局变量, 存在于任何的函数定义之外, 一直存在于整个程序的生命周期
类内static成员如何声明定义?
- 在类内部声明, 外部通过类名作用域访问定义
{
class MyStatic
public:
static int i_stc; // 类内部声明
// ...
}
int MyStatic::i_stc = 0; // 类外部定义, 注意需要声明成员的类型
也可以通过静态成员函数和一般的成员函数对它进行修改, 此时静态成员函数可通过类名访问。
在不同实例中被多次调用改变后的情况?
void MyStatic::increment() {++i_stc;} |
c0 = 1 |
静态数据成员类似于全局变量, 无论在何处, 每调用一次修改静态成员的函数, 数据相应的改变, 且不会随着作用域的离开而销毁。