C++中前置声明的使用
2017-12-08 22:15
302 查看
在编写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
{
private:
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
{
private:
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类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点,详见:特殊数据类型成员变量的初始化
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
{
private:
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
{
private:
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类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点,详见:特殊数据类型成员变量的初始化
相关文章推荐
- 【C/C++开发】C++之enum枚举量声明、定义、使用与枚举类详解与枚举类前置类型声明
- 为什么我们要使用c++的前置声明
- c++学习-类的前置声明与使用头文件区别
- 使用类前置声明的好处-结合Qt 4一个主窗口实例讲解
- 关于C++中的前置声明
- c++ 之类的前置声明
- c++之类的前置声明
- C++ 为什么要同时使用*和&符号?以及什么场合使用这种声明方式?
- C++中前置声明的应用与陷阱
- C++ 前置声明的问题
- c++ 之类的前置声明
- C++的前置声明
- C++之类的前置声明
- [C++]前置声明和头文件
- c++ 之类的前置声明
- 正确使用#include和前置声明
- 如何使用前置声明取代包括头文件
- 什么时候该使用前置声明?
- (了解)类前置声明实现接口和实现分离 必须使用指针 且不能作为基类
- 使用Delphi声明C++带函数的结构体实战