0
#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。我有一个抽象类想要实现test1test2用于实现test1.

现在 C 和 C1 以及我实现的具体类test2

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

错误:不能在没有对象的情况下调用成员函数 'virtual std::string A::test2()'

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

4

4 回答 4

3

不要纠结于纯虚拟与虚拟。中声明的两个函数A都是虚函数,您可以将它们视为虚函数。所以B的实现test1应该简单地调用test2. 没有A::预选赛。这会进行一次虚拟调用,最终会以最派生的版本结束test2,即定义在Cor中的版本C1,具体取决于对象的类型。在我删除A::from后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>

于 2013-05-07T11:59:46.340 回答
2

class B需要继承自class A.

class B: public A ... 

当然,调用A::test2()是行不通的,因为该类没有实现——它没有主体。您也可以通过在 A 类中实现它来解决这个问题,如下所示:

std::string A::test2() { return "some string"; }
于 2013-05-07T10:44:39.027 回答
2

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

于 2013-05-07T10:53:21.223 回答
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?";
}

请注意,由于语言的怪癖,不能在类定义中定义纯虚函数;这个定义必须在课堂之外。

于 2013-05-07T12:27:10.250 回答