簡體   English   中英

從抽象類繼承的模板類中正確使用未定義類型

[英]Proper use of undefined type in template class inheriting from abstract class

我有一個頭文件(例如the_foo.h ),它定義/聲明了以下類:

// \file the_foo.h

class FooBase
{
    virtual size_t bar_size() = 0;
};

template<class Bar>
class Foo : public FooBase
{
    size_t  bar_size()  { return sizeof(Bar); }
};

class TheBar;       // TheBar forward declaration

class TheFoo : public Foo<TheBar>
{
};

使用MS vc14(Visual Studio 2015)進行編譯時,我注意到以下行為:

  1. 任何包含the_foo.h並定義TheBar cpp文件,例如:

    #include "the_foo.h" class TheBar {}; // TheBar definition

    將編譯就好了。 然而,

  2. 任何包含the_foo.hNOT DEFINE TheBar cpp文件,例如:

    #include "the_foo.h"

    編譯失敗並出現錯誤: the_foo.h(11): error C2027: use of undefined type 'TheBar'

    上面編譯的cpp文件僅包含一行:包含標題,沒有更多代碼。
    刪除虛擬成員函數聲明virtual size_t bar_size() = 0; 確實解決了錯誤。
    感謝Sam Varshavchik的回答,此代碼可以使用gcc 5.3.1很好地進行編譯,因此,此問題顯然是特定於編譯器的。

我的問題是:

  • TheBar向前聲明TheBar時,為什么在情況(2)中編譯失敗?
  • 有沒有辦法使案例(2)在vc14下成功編譯,即沒有顯式定義TheBar ,我需要在某些cpp文件中保持哪個類不透明?

PS:我編輯了該問題的代碼示例,以弄清是什么真正導致了問題中所述的問題。 原始代碼示例(在Sam Varshavchik的答案中引用)可能確實誤導了問題的實際原因,因此導致了問題范圍之外的答案和注釋。

您的測試用例編譯時不會出現gcc 5.3.1問題:

$ cat t.C
class FooBase
{
public:
    FooBase()          {}
    virtual ~FooBase() {}
};

template<class Bar>
class Foo : public FooBase
{
public:
    Foo()   { sizeof(Bar); bar = new Bar; }
    ~Foo()  { sizeof(Bar); delete bar; }
    Bar*    bar;
};

class TheBar;

class TheFoo : public Foo<TheBar>
{
public:
    TheFoo();
    ~TheFoo();
};
[mrsam@octopus tmp]$ g++ -c -o t.o t.C
[mrsam@octopus tmp]$ 

答案似乎是“您使用的舊的C ++編譯器無法正確編譯”。

當您嘗試在Foo類的構造函數和析構函數中構造或刪除class TheBar時,編譯器會搜索class TheBar的定義。 這意味着它需要那時的實現,否則它不知道該怎么做。

如果使用以下示例:

第一個標頭:

// foobase.h

class FooBase
{
    public:
        FooBase()          {}
        virtual ~FooBase() {}
};

template<class Bar>
class Foo : public FooBase
{
    public:
        Foo()  { bar = new Bar; }
        ~Foo() { delete bar; }
    private:
        Bar* bar;
};

class TheBar;

class TheFoo : public Foo<TheBar>
{
    public:
        TheFoo() {};
        ~TheFoo() {};
};

下一個標題

// thebar.h

class TheBar {};

和以下主文件:

// foo_main.cxx

// #include "thebar.h" // Including this include makes the program run
#include "foobase.h"

int main()
{
    TheFoo thefoo;
    return 0;
}

然后,您的編譯器會告訴您哪里出了問題(僅顯示第一個錯誤):

./foobase.h:14:32: error: allocation of incomplete type 'TheBar'
        Foo()  { bar = new Bar; }

包括thebar.h將解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM