派生类的拷贝构造函数

<DIV class=cnt id=blog_text>

刚刚弄了一个关于派生类的实验,里面涉及到了派生类的拷贝构造函数,这时才发现自己在这个知识点上还很模糊。在CSDN上面看了下相关的一篇文章后,稍微有了点感觉。现总以一个例子总结如下:

情况(1). 派生类的copy   constructor未定义

#include   <iostream>  
using   namespace   std   ;  
   
class   base  
{  
public:  
base()   {   cout   <<   “base::base()”   <<   endl   ;   }  
base(   const   base&   )   {   cout   <<   “base::base(   const   base&)”   <<   endl   ;   }  
virtual   ~base()   {   cout   <<   “base::~base()”   <<   endl   ;   }  
};  
   
class   child   :   public   base  
{  
   
public:  
child()   {   cout   <<   “child::child()”     <<   endl   ;   }  
/——————————————————————  
child(   const   child&   )   {   cout   <<   “child::child(   const   child&   )” <<   endl   ;   }     
——————————————————————-
/  
~child()   {   cout   <<   “child::~child()”   <<   endl   ;   }  
int   test(int   i)   {   cout   <<   “int   child::test(int)”   <<   endl   ;  

return   0   ;   }  
   
};  
   
int main()  
{  
child   c1   ;  
cout   <<   “—————————-“   <<   endl   ;  
child   c2(c1)   ;  
cout   <<   “—————————-“   <<   endl   ;  
}  
输出结果:  
base::base()  
child::child()  
—————————-  
base::base(   const   base&)
—————————-  
child::~child()  
base::~base()  
child::~child()  
base::~base()  

注意 child   c2(c1)   ;   调用了基类的拷贝构造函数,这是为什么呢?因为派生类没有显式定义自己的拷贝构造函数,而基类定义了。首先child公有继承base,且base::copy   ctor也是public的,那么对child类而言,基类copy   ctor是可见的。 child   c2(c1)   ;   这句,编译器先找child自己的copy   ctor,没有。这时就去找基类的copy   ctor。由于它的参数是这样定义的:const   base&   ,即用到了基类对象的引用,所以这里有多态的能力,比如child   c2(c1)   ;

看下面这个例子

#include   <iostream>  
using   namespace   std   ;  
   
class   base  
{  
public:  
base(){cout<<”base::base()”<< endl;}  
base(const base& rhs)  
{  
cout<<”base::base(const base&)”<<endl;    
rhs.show();    
}  
virtual   void show() const {cout<<”base::show()”<<endl;}  
virtual   ~base()   {cout<<”base::~base()”<<endl;}  
};  
   
class   child:public base  
{  
public:  
child()   {cout<<”child::child()”<<endl;}  
/——————————————————————  
child(   const   child&   )   {   cout   <<   “child::child(   const   child&   )” <<   endl   ;   }     
——————————————————————-
/  
~child(){cout<<”child::~child()”<<endl;}  
virtual void show()const {cout<<”child::show()”<<endl;}  
int test(int i) {cout<<”int child::test(int)”<<endl;return 0;}  
};  
   
int   main()  
{  
   child   c1   ;  
   cout<<”—————————-“<<endl;  
   child   c2(c1);  
   cout<<”—————————-“<<endl;  
}  

输出为:

base::base()  
child::child()  
—————————-  
base::base(   const   base&)  

child::show()
—————————-  
child::~child()  
base::~base()  
child::~child()  
base::~base()  

2基类也没有显式定义自己的拷贝构造函数

#include <iostream>
using namespace std ;

class base
{
public:
base() { cout << “base::base()” << endl ; }
/base( const base& ) { cout << “base::base( const base&)” << endl ; } /
virtual ~base() { cout << “base::~base()” << endl ; }
};

class child : public base
{

public:
child() { cout << “child::child()” << endl ; }
/——————————————————————
child( const child& ) { cout << “child::child( const child& )” << endl ; }   
——————————————————————-
/
~child() { cout << “child::~child()” << endl ; }
int test(int i) { cout << “int child::test(int)” << endl ; return 0 ; }

};   
    
   int main()
{
child c1 ;
cout << “—————————-“ << endl ;
child c2(c1) ;
cout << “—————————-“ << endl ;
}  

输出结果:
base::base()
child::child()

—————————-   

child::~child()
base::~base()
child::~child()
base::~base()  

这时child c2(c1) ; 调用的是自己的默认拷贝构造函数,同时也会调用基类的默认构造函数(为什么是构造函数不是拷贝构造函数,下面的一种情况就会看到),既然默认的构造函数什么所以不会有什么输出信息。

3基类和派生类都显式定义了自己都拷贝构造函数

#include <iostream>
using namespace std ;

class base
{
public:
base() { cout << “base::base()” << endl ; }   
base( const base& ) { cout << “base::base( const base&)” << endl ; }   
virtual ~base() { cout << “base::~base()” << endl ; }
};

class child : public base
{

public:
child() { cout << “child::child()” << endl ; }   
child( const child& ) { cout << “child::child( const child& )” << endl ; }   
~child() { cout << “child::~child()” << endl ; }
int test(int i) { cout << “int child::test(int)” << endl ; return 0 ; }

};   
    
   int main()
{
child c1 ;
cout << “—————————-“ << endl ;
child c2(c1) ;
cout << “—————————-“ << endl ;
}  

输出为:

base::base()

child::child()

base::base()

child::child( const child& )

child::~child()
base::~base()
child::~child()
base::~base()  

注意这里child c2(c1) ;   调用了基类的构造函数而不是拷贝构造函数,这又是为什么呢?
请问拷贝构造函数是不是构造函数??    是,是个特殊的构造函数,但是他也是构造函数。C2调用自己的拷贝构造函数的时候,编译器只是认为你调用了构造函数,根据参数类型是调用我们所说的拷贝构造函数,但是当他决定调用基类的哪个构造函数的时候,他要看你传递给基类的参数了,你什么都没有给传递,当然调用默认构造函数了。

我想通过上面三种情况的讲解大家应该都能明白派生类拷贝构造函数的奥妙了,通过这个例子也对我学习C++的过程敲了下警钟:知识面还是不广,综合运用所学东西的能力还不够,尤其是那个多态的地方,如果是单独的多态可能一下子就看出来了,但是用在这里就傻眼了。