使用子方法 c++

Use a children method c++

本文关键字:c++ 子方法      更新时间:2023-10-16

我有这些对象:

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 对象

感谢您的帮助

您不会覆盖该函数。为此,请在 A 类中声明此函数时使用"virtual"关键字。

您忘了将成员函数设为虚拟

简短的回答是:按照其他答案的指示使用 virtual,以便覆盖该函数,而不是隐藏它。

以下是 Herb Sutter 的 Exceptional C++ - Item 21: Overoverride Virtual Functions 的摘录,其中更详细地解释了您的代码发生了什么:

区分三个常用术语非常重要:

  • 重载一个函数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 的非虚拟函数。

多态性需要使用 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 关键字不是必需的(如果基类函数声明为 virtual,则会隐式添加到派生类中),但可以很好地用于提高可读性并避免需要它的奇数编译器的潜在问题。override标识符也不是必需的,但会强制编译器检查您是否确实覆盖了超类中存在的虚函数。(我认为覆盖仅在 C++11 中可用)。