关于c ++:抽象对象无法声明

Abstract object cannot declare

我对抽象/虚拟类有问题,这里是对问题的复制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>

class A
{
protected:
    virtual std::string getDateTime() = 0;
    virtual void Write(std::string data, bool addDate) = 0;
    virtual bool CheckFile() = 0;
    virtual bool OpenFile(std::string path) = 0;
    virtual void CloseFile() = 0;
};

class B
    : public A
{
public:
    virtual std::string ToString() { return""; };
    virtual void Write(std::string data) { };
};

class C
    : public A
{
protected:
    std::string getDateTime()
    {
        return"TODAY";
    };

    void Write(std::string data, bool addDate)
    {
        std::cout <<"BasicClassA Write" << std::endl;
    };

    bool CheckFile()
    {
        std::cout <<"BasicClassA CheckFile" << std::endl;
        return true;
    };

    bool OpenFile(std::string path)
    {
        std::cout <<"BasicClassA OpenFile" << std::endl;
        return true;
    };

    void CloseFile()
    {
        std::cout <<"BasicClassA CloseFile" << std::endl;
    };
};

class D
    : public B,
      public C
{
public:
    BasicClassB();
    virtual ~BasicClassB();

    std::string ToString()
    {
        return"BasicClassB tostring";
    };

    void Write(std::string data)
    {
        std::cout <<"BasicClassB Write" << std::endl;
    };
};

int main(int ac, char *av[])
{
    BasicClassB b;
    std::cout << b.ToString() << std::endl;
    b.Write("");
    return 0;
}

这有一个编译错误:

../src/main.cpp:在函数"int main(int,char**)"中:../src/main.cpp:82:错误:无法将变量"b"声明为抽象类型"basicclassb"../SRC/main.cpp:64:注意:因为以下虚拟函数在"basicClassB"中是纯的:./SRC/main .CPP:13:注释:虚拟STD::字符串BaseCasa::GETDATITEME()./SRC/main .CPP:14:注释:虚拟空隙BaseCasa::写(STD::字符串,BOOL)../src/main.cpp:15:注意:虚拟bool baseclassa::checkfile()./SRC/main .CPP:16:注释:虚拟BooBaseCasa::OpenFILE(STD::字符串)../src/main.cpp:17:注意:虚拟void baseclassa::closefile()

也许我这里遗漏了一点,但是baseclassa(basicclassa)的实现应该包含这些函数,而且由于basicclassb也是basicclassa的子类,所以它也应该包含这些函数?

我错过了什么?我该怎么做才能编译这个程序?

[编辑]I updated the class names as suggested by the comment。澄清:我在A班使用了纯虚拟来强制任何一个孩子实现这些功能。

我需要的似乎是虚拟继承,但是,在我的案例中,我似乎没有找到正确的方法来实现这一点…

目标是要有几个"基本"类,类似接口,强制子类实现函数,但是这些类的任何子类都应该继承覆盖函数(就像虚拟继承一样)。

但是,使用任意类:公共虚拟任意其他不可行,总是给出相同的编译错误(上面的那个)。也许我需要改变的不仅仅是继承中的虚拟?


默认情况下,C++中没有这样的工作方式——你想要一个菱形继承模式,但是在C++中你得到了独立的根:所以BasicClassA和BaseClassB每个都有自己的BaseCasa(VTABLE和实例变量)。

您可能想要使用虚拟继承。

要更清楚地了解非虚拟继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>


class A
{
    public:
        A(int x) {m_a = x;}
        virtual ~A() {}
        int m_a;
        virtual int getA() {return m_a;}
};

class B : public A
{
    public:
        B() : A(1) {}
};

class C : public A
{
    public:
        C() : A(2) {}
};

class D : public B,
          public C
{
};

void useB(B* b)
{
    std::cout <<"useB:" << b->getA() << std::endl;
}

void useC(C* c)
{
    std::cout <<"useC:" << c->getA() << std::endl;
}

int main()
{
    D* d = new D();
    useB(d);
    useC(d);

    return 0;
}

这将产生输出:

1
2
useB:1
useC:2

这个例子展示了虚拟继承,以及您想要的混合行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>


class A
{
    public:
        A(int x) {m_a = x;}
        virtual ~A() {}
        int m_a;
        virtual int getA() {return m_a;}
        virtual int virt() = 0;
};

class B : virtual public A
{
    public:
        B() : A(1) {}
};

class C : virtual public A
{
    public:
        C() : A(2) {}
        virtual int virt() {return 42;}
};

class D : public B,
          public C
{
    public:
        D() : A(3) {}
};



void useB(B* b)
{
    std::cout <<"useB:" << b->getA() << std::endl;
}

void useC(C* c)
{
    std::cout <<"useC:" << c->getA() << std::endl;
    std::cout <<"useC-virt:" << c->virt() << std::endl;
}

int main()
{
    D* d = new D();
    useB(d);
    useC(d);

    return 0;
}

输出:

1
2
3
useB:3
useC:3
useC-virt:42

注意:C和B的构造函数在设置m_时没有发言权,m_a是d()构造函数初始化列表的控制器。

编辑:将虚拟应用于代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>

class A
{
protected:
    virtual std::string getDateTime() = 0;
    virtual void Write(std::string data, bool addDate) = 0;
    virtual bool CheckFile() = 0;
    virtual bool OpenFile(std::string path) = 0;
    virtual void CloseFile() = 0;
};

class B
    : virtual public A
{
public:
    virtual std::string ToString() { return""; };
    virtual void Write(std::string data) { };
};

class C
    : virtual public A
{
protected:
    std::string getDateTime()
    {
        return"TODAY";
    };

    void Write(std::string data, bool addDate)
    {
        std::cout <<"C Write" << std::endl;
    };

    bool CheckFile()
    {
        std::cout <<"C CheckFile" << std::endl;
        return true;
    };

    bool OpenFile(std::string path)
    {
        std::cout <<"C OpenFile" << std::endl;
        return true;
    };

    void CloseFile()
    {
        std::cout <<"C CloseFile" << std::endl;
    };
};

class D
    : public B,
      public C
{
public:
    std::string ToString()
    {
        return"D tostring";
    };

    void Write(std::string data)
    {
        std::cout <<"D Write" << std::endl;
    };
};

int main(int ac, char *av[])
{
    D b;
    std::cout << b.ToString() << std::endl;
    b.Write("");
    return 0;
}


BasicClassB只派生自BaseClassA这是一个抽象类,因为这些方法:

1
2
3
4
5
virtual std::string getDateTime() = 0;
virtual void Write(std::string data, bool addDate) = 0;
virtual bool CheckFile() = 0;
virtual bool OpenFile(std::string path) = 0;
virtual void CloseFile() = 0;

纯粹是虚拟的。

错误消息非常清楚:为了能够实例化BasicClassB,您必须为前面提到的方法提供一个实现。

另外,请注意您在BasicClassB中对Write的定义:

1
virtual void Write(std::string data) { };

BaseClassA中的不同:

1
virtual void Write(std::string data, bool addDate) = 0;

因此,为了使BasicClassB成为可实例化的,仍然需要实现这种方法。


BaseClassA有5个纯虚拟函数。具有一个纯虚函数的类是一个"抽象类"。纯虚拟函数(简而言之)的目的是禁止创建抽象类的对象。

为了实例化baseclassb,它需要定义您在baseclassa中声明为纯虚拟的所有5个函数。(在没有这些定义的情况下,baseClassB也变得抽象,因此不能从中创建对象)。


向函数中添加"=0"意味着它们是纯虚拟的,必须在子类中实现。这显然不是你想要的。如果从基类中具有实现的函数中除去"=0",则它应该按预期工作。