zoukankan      html  css  js  c++  java
  • 函数传值 复制构造函数 深度拷贝

    class A{
    	int *m_pi;
    public:
    	A()
    	{
    		m_pi = new int;
    	}
    	~A()
    	{
    		delete m_pi;
    	}
    };
    
    void func(A _a)
    {
    	int a = 0;
    }
    
    void main()
    { 
    	A a;
    	func(a);
    }


    运行后崩溃,原因是当调用func时,产生一个临时对象,并未调用构造函数,调用默认的位拷贝复制构造函数,然后析构掉了 m_pi 的内存,程序结束析构a时崩溃,解决方案是重载拷贝构造函数


    class A
    {
    	int *m_pi;
    public:
    	A()
    	{
    		m_pi = new int;
    	}
    	~A()
    	{
    		delete m_pi;
    	}
    	A(A &_a)
    	{
    		m_pi = new int;
    		*m_pi = *_a.m_pi;
    	}
    };
    
    void func(A _a)
    {
    	int a = 0;
    }

    再考虑,在A中加一个CArray对象


    class A
    {
    	int *m_pi;
    	CArray <int,int &> m_arr;
    public:
    	A()
    	{
    		m_pi = new int;
    	}
    	~A()
    	{
    		delete m_pi;
    	}
    	
    };
    
    void func(A _a)
    {
    	int t = 0;
    }

    主函数:

        A a;
        func(a);


    编译报错:

    “CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)
    原因:func传入实参后会生成临时对象,用默认的拷贝构造函数初始化临时对象(因为这里未定义拷贝构造函数),而默认的拷贝构造函数会依次调用A类成员的拷贝构造函数,如果未定义,则会调用默认的,对于CArray来说,虽然未定义了拷贝构造函数,但其基类CObject定义了,但为private权限,编译报错。

    private:
        CObject(const CObject& objectSrc);              // no implementation
        void operator=(const CObject& objectSrc);       // no implementation

    对于赋值操作符,同样的
    主函数
        A a;
        A b;
        b = a;       // 不同于 A b = a  出现第一种错误,编译器?

    报错:
    “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)


    解决方案:

    重载操作符

        A &operator=(A &)
        {
            return *this;
        }

    定义拷贝构造函数

        A(A &)
        {
        }


    再考虑

    class A
    {
    	int m_a;
    	CArray <int,int> m_arr;
    public:
    	A(int i){};
    };
    
    void main()
    {
    
    	A a;
    	CArray<A,A &> arr;
    	arr.Add(a);
    }

    报错:
    “A”没有合适的默认构造函数可用
    原因:
    可能是因为进入CArray的类型必需有不带参数构造函数,我们将带参数构造函数去掉
    http://hi.baidu.com/idealsoft/item/4de85dcac49b2c2847d5c07d
    报错:
    “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)
    原因:

    arr.Add(a) 时,会调用A的=,而未定义,则逐次调用成员的,包括CArray成员m_arr,因为Add函数的签名要求输入参数的类型为A&,所以当编译器编译语句:arr.Add(a); 时会自动将a强制转换成A的引用,即将这条语句编译成:A& newElement = b; arr.Add(newElement); 赋值操作就这样出现了!解决方案:定义=操作符

        A &operator=(A&)
        {
            return *this;
        }

    http://blog.csdn.net/vincent_lon/article/details/2950218


    此外,若将CArray参数改为传值CArray<A,A> arr;,则报错:

    “CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)


    add 的参数变为值传递,需要拷贝构造函数支持,而我们的类没有,CArray同样没有,CObject有,但是私有,所以编译报错,解决方案为定义拷贝构造函数:

        A(A &){}
        A(){}

    别忘了再定义一个无参数构造函数


    结论:当你的类有CArray成员时,

    1 值类型,为类准备无参数构造函数,拷贝构造函数和=重载函数。

    2 引用类型,=操作符,无参数构造函数



    ps : 2014.6.18

    “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)

    “CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)


    CArray 继承自 CObject, 而CArray只显式定义了无参数默认构造函数,而没有定义拷贝构造和赋值操作符重载函数,A在未定义相关函数的情况下进行拷贝或赋值操作时,

    依次调用类体各成员对象的拷贝和赋值操作符重载函数,对于CArray对象,由于未显式定义拷贝和赋值操作符重载函数,故编译器在自动生成的 copy及”=“函数中,调用基类CObject 的拷贝构造 和 ”=“操作符函数,而这两个函数正被CObject声明为private权限,即使在派生类CArray中亦无法访问。


    得出:

    在设计一个基类时,

    1.禁止该类被直接实例化,则将构造函数申明为 private or protected,当申明为private时,该类及其所有派生类都无法实例化,如:

    class A
    {
    private:
    	A(){}
    };
    
    class B : public A
    {
    public:
    	B(){}
    };

    error C2248: “A::A”: 无法访问 private 成员(在“A”类中声明)


    2.如果处于安全考虑,强制要求其派生类在显式定义 复制控制(拷贝构造和赋值操作符函数),则可将 2个复制控制函数申明为private,如果申明为 protected,则只能在类及派生类体内进行对象复制操作。






  • 相关阅读:
    Python学习第二天
    Python学习第一天
    linux下使用命令修改IP地址
    Java消息队列
    转:《什么是敏捷软件测试》
    测试流程优化
    MacOS安装使用Kettle
    用OneNote写博客的方法
    Matlab给三维点云添加高斯噪声和随机噪声
    如何高效完成英文文献翻译
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106894.html
Copyright © 2011-2022 走看看