在抽象类中使用纯虚方法

时间:2013-05-07 10:42:40

标签: c++

#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <string>
class A{
public:
    virtual void test1() = 0;
    virtual std::string test2() = 0;
};

class B : public A{

public:
     void test1(){
       std::cout << A::test2() << " World";
    }
};
class C : public B{
public:
     std::string test2(){
        return "hello";
    }
};
class C1 : public B{
public:
     std::string test2(){
        return "Sup";
    }
};

#endif // TEST_H

我有一个只有纯虚方法的接口A.我有一个抽象类,希望实现test1并使用test2来实现test1

现在C和C1以及实现test2

的具体类

但我不能在B级做std::cout << A::test2() << " World";

  

错误:无法调用成员函数'virtual std :: string A :: test2()'   没有对象

我如何在c ++中做这样的事情?

4 个答案:

答案 0 :(得分:3)

不要挂在纯虚拟虚拟网络上。在A中声明的两个函数都是虚函数,您可以这样处理它们。因此,B test1的实施应该只需拨打test2。没有A::限定符。这会进行虚拟调用,并最终会导致test2的最衍生版本,即CC1中定义的版本,具体取决于对象的类型。从A::中删除A::test2()后,以下代码正常工作(应该如此):

int main() {
    C c;
    c.test1();
    C1 c1;
    c1.test1();
    return 0;
}

[work]$ g++ test.cpp
[work]$ ./a.out
hello WorldSup World[work]$ 

是的,您应该在输出中添加\n<g>

答案 1 :(得分:2)

您的class B需要继承class A

class B: public A ... 

当然,调用A::test2()将无效,因为该类未实现 - 它没有正文。您可以通过ALSO在A类中实现它来解决这个问题,如下所示:

std::string A::test2() { return "some string"; }

答案 2 :(得分:2)

如果您想要虚拟呼叫,请不要使用显式范围限定。使用A::test2将尝试调用A::test2,而无需动态调度。反过来,这将无法链接,因为A::test2没有实现。

答案 3 :(得分:2)

错误消息暗示,在编译它时,B未从A继承,因此没有类型A的对象来调用成员函数。您发布的代码给出了一个不同的错误:A::test2未定义。

几乎可以肯定,你想虚拟地调用这个函数(即在CC1或其他任何地方调用最终覆盖)。在这种情况下,根本不符合条件:

std::cout << test2() << std::endl;

您的代码尝试专门调用A中声明的版本,而不是任何覆盖。如果这实际上是你想要的(我怀疑),那么需要定义该函数:

std::string A::test2() {
    return "I'm a pure virtual function. Why are you calling me?";
}

请注意,由于语言中的怪癖,无法在类定义中定义纯虚函数;这个定义必须走出课堂。