如何从基类函数调用覆盖的虚函数?

时间:2011-11-06 12:49:43

标签: c++ inheritance pure-virtual

我刚刚意识到我过多地简化了代码并且它没有反映我真正的问题。我为不具体而道歉。我实际上要做的是以下几点:

online Demo

#include<iostream>

class A
{
    public:
        A();

        virtual void f()= 0;
        void g();
};

A::A()
{
    g();
}

void A::g()
{
    f();
}

class B : public A
{
    public:
        B() {};
        void f() {};
};

int main()
{
    B b;
    return 0;
}

我想程序调用纯虚函数A::f,因为在调用构造函数时尚未创建B

这是正确的,我该如何克服这个问题?

请原谅我之前提出过于简化的问题。

6 个答案:

答案 0 :(得分:5)

在删除了很多其他错误后,代码的

Working sample

#include<iostream>

class A 
{
    virtual void f()=0;
    public:
    void g();
};

void A::g() 
{
   f();
}

class B : public A 
{

    void f(){std::cout<<"Inside B::f";}
};

int main() 
{
    B b;
    b.g();
    return 0;
}

输出

  

内部B :: f

发布您的真实代码,以获取真正的答案。


修改
现在,您向我们展示了您的真实代码(它有编译错误,我为您修复了它们)。我理解你的问题。

使用B创建类B b;的对象时,会导致调用基类构造函数A::A(),而后者又调用方法g()。请注意,g()只是一个基类方法,因此会调用A::g()。这进一步调用了f()。现在你的期望是这应该调用B::f(),但事实并非如此。

<强> WHY吗
请注意规则,
在构造函数或析构函数中,对象this指向的类型始终是调用其构造函数/析构函数的类型。

应用上述规则,因为在f()的构造函数中调用了A,所以 this->f()调用A::f()而非B::f()。此外,因为A::f()没有定义(因为你没有提供定义)它会导致运行时异常:

  

称为纯虚方法   在没有活动异常的情况下终止调用。

编译器无法将此检测为编译时错误,因为virtual要调用的函数在运行时确定,具体取决于this指向的内容而非静态指向。编译器无法检测到这一点。

我如何克服这个问题?
您无法通过构造函数中的动态分派来完成此任务 如果从构造函数/析构函数之外的任何其他方法调用它,您可以实现并期望您期望的行为。

避免在构造函数和析构函数中调用虚函数,因为它们不会调用您可能会调用的版本。

答案 1 :(得分:0)

如果B :: f的函数签名与A :: f匹配,那么在A :: g中使用f()应该根据需要调用B :: f。在上面的示例中,它们匹配,A :: g应该调用B :: f。

如果您的真实函数签名比上面给出的示例更复杂,请确保它们的签名完全匹配,否则编译器会将B :: f视为新函数而不是覆盖A :: f。

*:严格来说,返回类型可能略有不同,但我希望这里不相关

答案 2 :(得分:0)

删除编译器错误后,your code works fine

答案 3 :(得分:0)

从概念上讲,这应该有效。我已经很久没有使用过C ++了,但这与C#中的这种情况不一样:

public class MyBase
{
    public virtual void PrintName() { }
    public void DoWork()
    {
        PrintName();
    }
}

public class MyDerivative : MyBase
{
    public override void PrintName()
    {
        Console.WriteLine("MyDerivative");
    }
}

答案 4 :(得分:0)

#include <iostream>

class A {
public:
    virtual void f() = 0;
    void g();
};

void A::g() {
    std::cout << "A::g" << std::endl;
    this->f();
}

class B : public A {
public:
    virtual void f();
};

void B::f()
{
    std::cout << "B::f" << std::endl;
}

int main() {
    B b;
    b.g();
    return 0;
}

答案 5 :(得分:0)

在源代码中添加:

void B::f()
{
    printf("im B::f\n");
}

并且您的计划应该有效。

您无法创建A的实例,因为存在纯虚方法。