C++ 类声明 类前置声明范例

转载自http://www.cnblogs.com/staring-hxs/p/3244251.html

在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration)。下面的程序中,带注释的那行就是类B的前置说明。这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面。如果没有类B的前置说明,下面的程序将不同通过编译,编译器将会给出类似“缺少类型说明符”这样的出错提示。

代码一:
// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
         A(B* b):b(b){}
};

class B
{
};

// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
         delete a;
         delete b;
         return 0;
}

上面程序可以顺利编译和运行(几乎没有做什么,也没有输出)。

是不是有了前置说明就万事大吉了呢?我们看看下面的代码(带阴影部分的代码是新增加的):

代码二:
// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
         A(B* b):b(b){}        void someMethod()
         {
            b->someMethod();                                                  // (1)
         }
};

class B
{
public:      void someMethod()       {
          cout << "something happened..." << endl;
       }
};

// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
    a->someMethod();    delete a;    delete b;
    return 0;
}

一编译,发现代码(1)处出错。出错提示往往包括(不同的编译器给出的提示会有所不同):

1. 使用了未定义的类型B;

2. “->somemethod”的左边必须指向类/结构/联合/泛型类型

原因:

1. (1)处使用了类型B的定义,因为调用了类B中的一个成员函数。前置声明class B;仅仅声明了有一个B这样的类型,而并没有给出相关的定义,类B的相关定义,是在类A后面出现的,因此出现了编译错误;

2. 代码一之所以能够通过编译,是因为其中仅仅用到B这个类型,并没有用到类B的定义。

解决办法是什么?

将类的声明和类的实现(即类的定义)分离。如下所示:

// ForwardDeclaration.h   类的声明
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
        A(B* b);
void someMethod();
};

class B
{
public:
void someMethod();
};

// ForwardDeclaration.cpp        类的实现
#include "ForwardDeclaration.h"
A::A(B* b):b(b)
{

}
void A::someMethod()
{
    b->someMethod();
}

void B::someMethod()
{
    cout << "something happened..." << endl;
}

// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
         a->someMethod();
     delete a;         delete b;
     return 0;
}

结论:

前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。

而且需要注意,如果将类A的成员变量B* b;改写成B& b;的话,必须要将b在A类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点

见:

特殊数据类型成员变量的初始化

但是我的测试还是不行

时间: 2024-11-19 01:15:16

C++ 类声明 类前置声明范例的相关文章

详解C++ 类的前置声明的使用

刚开始学习c++的人都会遇到这样的问题: 定义一个类 class A,这个类里面使用了类B的对象b,然后定义了一个类B,里面也包含了一个类A的对象a,就成了这样: //a.h #include "b.h" class A { .... private: B b; }; //另一个头文件 b.h #include "a.h" class B { .... private: A a; }; 一编译,就出现了一个互包含的问题了,这时就有人跳出来说,这个问题的解决办法可以这

C++中类的前置声明和包含头文件的区别

一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,假设我们有两个类A和B,分别定义在各自的头文件A.h和B.h中,但是在A中要用到B,B中也要用到A,但是这样的写法当然是错误的: class B; class A{ public: B b;}; class B{ public: A a;}; 因为在A对象中要开辟一块属于B的空间,而B中又有A的空间,是一个逻辑错误,无法实现的,在这里我们只需要把其中的一个A类中的B类型成员改成指针形式就可以避免这个无限延伸的怪圈了,为什么要更改A而

C++_前置声明

为什么要有前置声明? eg: -定义一个类 class A,这个类里面使用了类B的对象b,然后定义了一个类B,里面也包含了一个类A的对象a,就成了这样: //a.h #include "b.h" class A { .... private: B b; }; //b.h #include "a.h" class B { .... private: A a; }; 一编译,就出现了一个相互包含的问题了,解决的方法是在a.h文件中声明类B,然后使用B的指针. //a.h

C++中前置声明的应用与陷阱

前置声明的使用 有一定C++开发经验的朋友可能会遇到这样的场景:两个类A与B是强耦合关系,类A要引用B的对象,类B也要引用类A的对象.好的,不难,我的第一直觉让我写出这样的代码: // A.h #include "B.h" class A { B b; public: A(void); virtual ~A(void); }; //A.cpp #include "A.h" A::A(void) { } A::~A(void) { } // B.h #include

c++ 类前置声明【转】

[转自 here] 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration).下面的程序中,带注释的那行就是类B的前置说明.这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面.如果没有类B的前置说明,下面的程序将不同通过编译,编译器将会给出类似"缺少类型说明符"这样的出错提示. 代码一: // ForwardDeclaration.h #include <iostream> using namespace std; class B;

Java语言程序设计 上机实验4 掌握声明接口、一个类实现接口的声明和使用方法

Java语言程序设计 上机实验4 实验目的: 理解接口的作用,理解接口和实现接口的类的关系,掌握声明接口.一个类实现接口的声明和使用方法:熟悉Java语言包和实用包中的常用类. 实验内容:(*)为选做 声明圆柱体类Cylinder,继承椭圆类Ellipse(实现周长Perimeter接口和面积Area接口),为圆柱体类设计较为全面的构造方法,并实现体积Volume接口,计算表面积和体积. 将Java的若干关键字(15个以上)保存在一个字符串数组中,对其按升序排列,再采用顺序查找和二分法查找,判断

delphi自己声明类及其调用方法

{type放在interface下的uses引用单元下面} 1 // 声明类 2 type 3 TMyclass = class //注意这里不能加';' 因为这是个整体 4 data: integer; //类的域 5 procedure ChangeData(Value: integer); // 类的方法(过程)按住Ctrl + shift + c键自动生成函数体 6 function GetData:integer; //类的方法(函数) 7 // 类的域和方法可以根据自己的需要添加 8

jsp 声明类的使用

可以在"<%!"和"%>"之间声明一个类,该类在JSP页面内有效,即在JSP页面的Java程序片部分可以使用该类创建对象.在下面的例子中,我们定义了一个Circle类,该类的对象负责求圆的面积和周长.当客户向服务器提交圆的半径后,该对象负责计算圆的面积和周长. <%@ page contentType="text/html;charset=GB2312"%> <%@ page import="java.io

C++ Primer 学习笔记_15_类与数据抽象(1)_类的定义和声明

C++ Primer 学习笔记_15_类与数据抽象(1)_类的定义和声明 在C++中,用类来定义自己的抽象数据类型.通过定义类型来对应所要解决的问题中的各种概念,可以使我们更容易编写.调试和修改程序.可以使得自己定义的数据类型用起来与内置类型一样容易和直观. 看一下Sales_item类: class Sales_item { private: std::string isbn; unsigned units_sold; double revenue; public: double ave_pr