Chinaunix首页 | 论坛 | 博客
  • 博客访问: 491946
  • 博文数量: 72
  • 博客积分: 1851
  • 博客等级: 上尉
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-16 17:50
文章分类

全部博文(72)

文章存档

2013年(1)

2012年(17)

2011年(51)

2010年(3)

分类: C/C++

2011-05-24 21:18:48

C++中的构造函数与析构函数不会在继承中被子类所继承,默认的构造函数(参数表为空)会自动调用,不管是否为显示调用,但是如果基类的构造函数带有参数时,需要进行显示调用,否则会进行报错。如:

  1. #include <iostream>
  2. using namespace std;

  3. class A
  4. {
  5. public:
  6. A(int){cout<<"constructor A(int)"<<endl;}
  7. };
  8. class B:public A
  9. {
  10. public:
  11. B(int i):A(i){cout<<"constructor B()"<<endl;}
  12. };

  13. int main()
  14. {
  15. B b(1);
  16. return 0;
  17. }

如果注释调显示调用构造函数A(i),则由于基类找不到合适的构造函数而进行报错。

在一般的类进行初始化时,顺序为:声明部分(调用默认空列表构造函数)-->类的构造函数

而赋值重载函数,复制构造函数也存在类似的道理,如果显示定义赋值重载函数,复制构造函数就需要进行显示调用,否则基类调用就会失败,但是如果没有定义赋值重载函数,复制构造函数,则就会默认调用基类的构造函数,这些性质在其他的重载函数中也存在。

  1. #include <iostream>
  2. using namespace std;

  3. class GameBoard
  4. {
  5. public:
  6.   GameBoard(){cout<<"GameBoard()\n";}
  7.   GameBoard(const GameBoard&){

  8.     cout<<"GameBoard(const GameBoard&)"<<endl;
  9. }
  10. GameBoard& operator=(const GameBoard&){
  11.     cout<<"GameBoard::operator=()"<<endl;
  12.     return *this;
  13. }
  14. ~GameBoard(){cout<<"~GameBoard()"<<endl;}
  15. };

  16. class Game
  17. {
  18. GameBoard gb;
  19. public:
  20.   Game(){cout<<"Game()"<<endl;}
  21.  Game(const Game& g):gb(g.gb){
  22.     cout<<"Game(const Game&)"<<endl;
  23. }
  24.  Game(int){cout<<"Game(int)"<<endl;}
  25. Game& operator=(const Game&g){
  26. gb = g.gb;
  27. cout<<"Game::operator=()"<<endl;
  28. return *this;
  29. }
  30. class Other{};
  31. //Automatic type conversion:
  32. operator Other()const{
  33.  cout<<"Game::operator Other()"<<endl;
  34. return Other();
  35. }
  36. ~Game(){cout<<"~Game()"<<endl;}
  37. };
  38. class Chess:public Game{
  39. GameBoard gb;
  40. };
  41. int main()
  42. {
  43.  cout<<"Chess d1:"<<endl;
  44.   Chess d1;
  45.  cout<<"chess d2(d1)"<<endl;
  46.   Chess d2(d1);
  47.  cout<<" d1=d2 "<<endl;
  48.   d1 = d2;
  49.  cout<<"ending d1=d2"<<endl;
  50. }

编译上面代码,运行如下:

  1. Chess d1:
  2. GameBoard()
  3. Game()
  4. chess d2(d1)
  5. //基类复制 函数默认被调用,因为基类中赋值函数显示调用
  6. GameBoard(const GameBoard&)
  7. Game(const Game&)
  8. d1=d2
  9. //默认赋值函数被调用,连内部成员函数的赋值函数也会被调用!!
  10. GameBoard::operator=()
  11. GameBoard::operator=()
  12. Game::operator=()
  13. ending d1=d2

如果显示定义了复制,赋值函数的话,这些默认函数就不会被调用了,如:

  1. class Chess:public Game{
  2. GameBoard gb;
  3. public:
  4. Chess(){cout<<"chess constructor"<<endl;}
  5. Chess(const Chess& c1){cout<<"chess copy-constructor"<<endl;}
  6. Chess& operator=(const Chess&c){
  7. cout<<"Chess operator=()"<<endl;
  8. return *this;
  9. }

编译运行如下:

  1. Chess d1:
  2. GameBoard()
  3. Game()
  4. GameBoard()
  5. chess constructor
  6. chess d2(d1)
  7. GameBoard()
  8. Game()
  9. GameBoard()
  10. chess copy-constructor
  11.  d1=d2
  12. Chess operator=()
  13. //默认赋值函数没有被调用
  14. ending d1=d2

因此在基类有默认赋值,复制函数时,在子类进行重写过程中必须进行显示调用。

另外,如果一个函数的行参为基类对象则子类对象也可以调用该函数,称之为 “upcast”,如:

  1. void f(Game g){
  2. cout<<"f(Game g)"<<endl;
  3. }

  4. f(d1);

则结果如下:

  1. f(Game g)

阅读(3941) | 评论(0) | 转发(0) |
0

上一篇:sshfs分析心得(二)

下一篇:C++虚函数(一)

给主人留下些什么吧!~~