方法在派生时应该始终是虚拟的吗
Should method be always virtual when derived?
标题说明了一切(我不确定何时使用virtual
关键字(。在这种情况下,函数SaySomething()
应该是virtual
吗?(或者在使用指针时可能只应该是virtual
?(
#include <iostream>
class A{
public:
void SaySomething(){
std::cout << "aaaaaa";
}
};
class B : public A{
public:
void SaySomething(){
std::cout << "bbbbbbb";
}
};
int main(){
A objectA;
B objectB;
objectA.SaySomething();
std::cout << std::endl;
objectB.SaySomething();
return 0;
}
从技术上讲,在这种情况下,函数B::SaySomething
不需要是virtual
:编译器知道每个对象的运行时类型,因此在这两种情况下都会调用正确的方法。
然而,它与基类中的A::SaySomething
同名,但没有覆盖它,这可能会误导代码的读者。如果您计划隐藏,而不是覆盖类B
中的A::SaySomething
,那么最佳实践是为成员函数赋予不同的名称。
这是一个重要的情况:
B b;
A &ab(b);
b.SaySomething(); // Calls B::SaySomething
ab.SaySomething(); // Calls A::SaySomething
更改引用同一对象的方式时的行为更改方法的行为不是代码读者所期望的。如果将A::SaySomething
设为虚拟,则两个调用都会产生相同的行为。
virtual
关键字是在C++中启用多态性的原因。您的示例严格来说是非多态的,因为方法调用解析是静态的。所以在你的例子中没有必要。
然而,如果你有。。。
class Shape {
virtual double area() = 0;
}
class Circle : public Shape {
virtual double area() {
return PI * r * r;
}
}
class Square : public Shape {
virtual double area() {
return h * w;
}
}
代码。。。
Shape* shapes[2];
shapes[0] = new Circle(1);
shapes[1] = new Square(1, 1);
for (int i=0; i<2; i++)
cout << "shape[" << i << "] area -> " << shapes[i]->area();
将打印圆形和方形的面积。。。
shape[0] area -> 3.1415926..
shape[1] area -> 1
如果您有:
class A {
virtual void f() { cout << 1 << endl; }
};
class B : public A {
virtual void f() { cout << 2 << endl; }
};
然后当你在这样的代码中使用它时:
A* a = new B();
a->f();
您的程序将写入2,因为您使用了virtual
。它动态地解析所指向的对象是类型B,尽管指针是类型A。
如果不使用virtual
,它将打印1并使用指针类型类中的函数。
相关文章:
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 大小虚拟继承中的派生类
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 虚拟基类函数中派生类的大小
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 派生类中纯虚拟基方法的专业化
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- 无法在派生对象上运行虚拟函数
- googletest:测试基类具有纯虚拟方法的派生类时的核心转储
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 有没有办法在没有虚拟的情况下使用基类指针调用派生类函数
- 从基调用派生类的隐藏(非虚拟)方法
- 派生类可以有多个指向虚拟表的指针
- 如何从派生类函数中调用虚拟函数
- (为什么)纯虚拟派生类中是否需要虚拟基类构造函数调用?
- 虚拟派生和转换模棱两可
- 删除虚拟派生类的this和位置new