2011-11-06 74 views
-2

我刚刚意识到,我简化了代码太多,它并没有反映我真正的问题。我很抱歉没有更具体。我实际上是尝试做的是以下几点:如何从基类函数调用被覆盖的虚函数?

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; 
} 

我猜程序调用自BA::f已经在构造函数被调用尚未创建的纯虚函数。

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

请原谅我早些提供过于简化的问题。

+1

我也在等待回应。对于我所了解的C++,你不能构造一个类实例,其中类仍然有一些未实现的纯虚方法。 – Heisenbug

+0

几乎肯定存在你删除的代码中的一个错误。 –

+0

-1不是真实代码 –

回答

0

如果B :: f的函数签名与A :: f匹配,那么在A :: g中使用f()应该按照你的意愿调用B :: f。在你上面的例子中,它们匹配,A :: g应该调用B :: f。

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

*:严格来说,返回类型可能会稍有不同,但我相信这不是与此有关

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()但它没有。

为什么?
注意规则,
在构造函数中或析构对象的类型this点始终是它的构造/析构函数被调用的类型。

应用上面的规则,由于f()被称为在A构造,
this->f()电话A::f()而不是B::f()。另外,由于A::f()没有一个定义(因为你没有提供一个),这导致运行时异常:叫 终止所谓的不存在活跃异常

纯虚方法。因为virtual要调用的函数是在运行时根据什么this点,而不是静态确定

编译器检测不到这是编译时错误。编译器无法检测到这一点。

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

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

0

从概念上讲,这应该工作。我还没有在年龄C++,但是这不应该是从这个场景完全不同的C#:

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

和程序:

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

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

当然,在C#中,您会将MyBase和MyBase :: PrintName标记为抽象。 – xanadont

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; 
} 
0

源添加此应该管用。

由于存在纯粹的虚拟方法,因此无法创建A的实例。