C++ 嵌套类-将声明与C+中的定义分离+;

C++ 嵌套类-将声明与C+中的定义分离+;,c++,nested-class,C++,Nested Class,是否可以将类声明与其定义分开?当然是的,但是如果我想在这个类的实际定义之前有一个对象呢?考虑下面的例子: class ID3_Reader{ public: // code omitted for brevity protected: class Mp3_File; Mp3_File mFile; }; 很明显,它不会编译。我必须在ID3_R

是否可以将类声明与其定义分开?当然是的,但是如果我想在这个类的实际定义之前有一个对象呢?考虑下面的例子:

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        class Mp3_File;
        Mp3_File mFile;                                             
};
很明显,它不会编译。我必须在ID3_Reader类中定义Mp3_文件类。当我只有两节课的时候,这不是问题。如果有五个呢?我的代码会变得相当混乱。为了避免这个问题,我必须将类声明与其定义分开。我怎样才能做到这一点?请记住,我需要ID3_Reader类中的Mp3_文件类的一个实例。
我之所以使用嵌套类,是因为我不希望其他程序员使用Mp3\u文件类。我使用了“protected”关键字,因为我将基于ID3_Reader类创建类。

不是将
mFile
定义为
Mp3_文件的实例,而是将其定义为指向
Mp3_文件的指针。这样,您就不需要知道头文件中的定义。或者更好——使用智能指针。然后,您需要在类构造函数中使用
new
并在
ID3\u Reader
的析构函数中使用
delete
来创建实际实例

如果希望使用当前语法从类外访问
mFile
,请在访问器函数内取消对其的引用:

Mp3_File& getMp3(){ return *mFile; };

然后-如果
Mp3_文件
有一个重载的
操作符()
(或者事实上是任何其他重载操作符),则不需要每次手动取消引用它。

与其将
mFile
定义为
Mp3_文件
的实例,不如将其定义为指向
Mp3_文件
的指针。这样,您就不需要知道头文件中的定义。或者更好——使用智能指针。然后,您需要在类构造函数中使用
new
并在
ID3\u Reader
的析构函数中使用
delete
来创建实际实例

如果希望使用当前语法从类外访问
mFile
,请在访问器函数内取消对其的引用:

Mp3_File& getMp3(){ return *mFile; };

然后-如果
Mp3\u文件
有一个重载的
操作符()
(或者事实上是任何其他重载操作符),您就不需要每次手动取消引用它。

它不会编译,因为编译器不知道Mp3\u文件类将使用多少内存。如果你把它改成指针

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        class Mp3_File;
        Mp3_File *mFile;                                             
};
编译得很好(指针大小固定-)

我建议使用指针而不是完整的成员变量,并在ctor/dtor中初始化/取消初始化它


如果不改变“嵌套类”的设计,我看不到其他方法。它不会编译,因为编译器不知道Mp3\u文件类将使用多少内存。如果你把它改成指针

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        class Mp3_File;
        Mp3_File *mFile;                                             
};
编译得很好(指针大小固定-)

我建议使用指针而不是完整的成员变量,并在ctor/dtor中初始化/取消初始化它


如果不改变“嵌套类”的设计,我看不到其他方法可以做到这一点。

您可以通过使用指针来实现这一点。回想一下,尽管必须有一个完整的类来定义变量,但一个简单的前向声明可以很好地定义指针:

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        class Mp3_File;
        Mp3_File *mFile;                                             
};

不幸的是,这会让您在管理嵌套类的内存时陷入困境,但它确实会对外部程序员隐藏类的所有内部内容。

您可以通过使用指针来实现这一点。回想一下,尽管必须有一个完整的类来定义变量,但一个简单的前向声明可以很好地定义指针:

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        class Mp3_File;
        Mp3_File *mFile;                                             
};

不幸的是,这会使您在管理嵌套类的内存方面陷入困境,但它确实会对外部程序员隐藏该类的所有内部内容。

您可以将类设置为类模板,以解决此限制:对于类模板,嵌套类型的定义需要在实例化时可见,在查看类模板的定义时不需要。您可能希望使用
typedef
来实际命名所使用的实例化,以避免需要有尾随的
。下面是一个快速演示:

 template <typename = void>
 class ID3_ReaderT {
     public:
         // code omitted for brevity
     protected:
         class Mp3_File;
         Mp3_File mFile;                                             
 };
 typedef ID3_Reader<> ID3_Reader;

 template <typename  T>
 class ID3_ReaderT<T>::Mp3_File {
 };

 int main()
 {
     ID3_Reader reader;
 }
模板
类ID3_ReaderT{
公众:
//为简洁起见省略了代码
受保护的:
类Mp3_文件;
Mp3_文件mFile;
};
类型定义ID3_读卡器ID3_读卡器;
模板
类ID3\u ReaderT::Mp3\u文件{
};
int main()
{
ID3_阅读器;
}

当然,这仍然意味着
ID3\u Reader
的每个用户都需要查看嵌套类型的定义。如果您想避免这种情况,您的选择是在间接层上,即使用多个答案中已经说明的指针。

您可以将类设置为类模板来解决此限制:对于类模板,嵌套类型的定义需要在实例化时可见,在查看类模板的定义时不需要。您可能希望使用
typedef
来实际命名所使用的实例化,以避免需要有尾随的
。下面是一个快速演示:

 template <typename = void>
 class ID3_ReaderT {
     public:
         // code omitted for brevity
     protected:
         class Mp3_File;
         Mp3_File mFile;                                             
 };
 typedef ID3_Reader<> ID3_Reader;

 template <typename  T>
 class ID3_ReaderT<T>::Mp3_File {
 };

 int main()
 {
     ID3_Reader reader;
 }
模板
类ID3_ReaderT{
公众:
//为简洁起见省略了代码
受保护的:
类Mp3_文件;
Mp3_文件mFile;
};
类型定义ID3_读卡器ID3_读卡器;
模板
类ID3\u ReaderT::Mp3\u文件{
};
int main()
{
ID3_阅读器;
}

当然,这仍然意味着
ID3\u Reader
的每个用户都需要查看嵌套类型的定义。如果您想避免这种情况,您的选择是在间接层次上,即使用多个答案中已经说明的指针。

您可以像其他人回答的那样使用指针来实现这一点:

class Mp3_File; // forward declaration of class Mp3_File

class ID3_Reader{
    public:
        // code omitted for brevity
    protected:
        Mp3_File *mFile;                                             
};
或者你可以申报