我有这些对象:
class A{
public:
void print();
}
class B : public A{
public:
void print();
}
class C : public A{
public:
void print();
}
功能打印:
void A::print(){
cout << "A" << endl;
}
void B::print(){
cout << "B" << endl;
}
void C::print(){
cout << "C" << endl;
}
现在我有一个A对象的向量,可以包含A B或C
for(unsigned int i = 0; i<m_vA.size(); i++)
{
cout << m_vA[i]->print() << endl;
}
但每次函数返回A时,即使这是一个B或C对象
感谢您的帮助
答案 0 :(得分:3)
您不会覆盖该功能。为此,请在A类中声明此函数时使用“virtual”关键字。
答案 1 :(得分:2)
您忘了将成员函数虚拟。
答案 2 :(得分:2)
简短的回答是:使用virtual
作为其他答案指示,以便您覆盖该功能,而不是隐藏它。
以下摘录自Herb Sutter的 Exceptional C ++ - 第21项:覆盖虚拟函数,它更详细地解释了代码的用途:
区分三个常用术语非常重要:
重载函数
f()
意味着在同一范围内提供具有相同名称f()
的另一个函数但具有不同的功能 参数类型。实际调用f()
时,编译器会尝试 根据实际参数选择最佳匹配 提供。覆盖虚拟函数
f()
意味着提供另一个具有相同名称f()
的函数和相同的参数类型 派生班。在封闭范围(基类,外部类或命名空间)中隐藏函数
f()
意味着提供具有相同功能的另一个函数 内部作用域中的名称f()
(派生类,嵌套类或 命名空间),它将在封闭中隐藏相同的函数名称 范围。
因为您的各种print
函数都在嵌套作用域中,并且因为您没有提供virtual
关键字,所以每个函数都隐藏中的同名函数基类:
class A{
public:
void print();
}
class B : public A{
public:
void print(); // Hides A::print()
}
class C : public A{
public:
void print(); // Hides A::print() and B::print()
}
因此,当编译器执行名称解析时,它将在当前范围内查找(这是您调用该函数的类型的类定义),它将停在那里,因为它将找到非虚函数名称为print
。
答案 3 :(得分:0)
多态性需要使用virtual
关键字来声明该方法应存储在虚拟表( vtable )中,并在运行时查找其实现。
另请注意,您的类定义在结束括号后需要使用分号。
class A
{
public:
virtual void print()
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void print() override
{
cout << "B" << endl;
}
};
class C : public A
{
public:
virtual void print() override
{
cout << "C" << endl;
}
};
在旁注中,派生类中的virtual
关键字不是必需的(如果基类函数被声明为虚拟,则隐式添加在派生类中),但是为了可读性和避免潜在问题很好用与需要它的奇怪编译器。 override
标识符也不是必需的,但会强制编译器检查您实际上是否覆盖了超类中存在的虚函数。 (我认为覆盖仅适用于C ++ 11)。