构造函数和clone以及在继承中

本文详细解析了构造函数的工作原理及其在类实例创建过程中的作用,并探讨了克隆机制如何利用构造函数来创建对象的副本。

构造函数

  • 类实例的构造创建过程是:
    1.属性域被初始化为默认值(0,false,null)
    2.按照在类声明的顺序初始化初始化语句和初始化块.
    3.执行构造函数
    所以,一个默认的空的无参构造函数并没有初始化类的实例域.因为实例域先于构造而初始化完毕了.

  • 构造函数无法被继承

  • 如果一个类没有定义构造函数,编译器会自动创建一个,如下:
public class A(){}

也就是说自己定义一个无参无实现的构造函数和不写构造函数没有区别

  • 继承的子类的无参构造函数会自动调用父类的无参构造函数.
  • 子类的构造函数总是需要调用父类的构造函数.实际上无参的构造函数,如果没有显式调用父类构造函数,编译器就会自动调用super(),如下:
public class A(){
super(); //编译器自动添加
}
  • 在构造函数中super(),或者this() 总是第一个执行(当然,super()和this() 不能共存于一个构造函数内).这是因为方法是在栈中调用执行的的,后调用的会先完成.
public class A(){
i=1; //这个是错误的,编译不能通过
super(); //手动添加的
}

克隆clone

在子类实现覆盖父类的clone() 方法时需要调用super();如:

 @Override 
 public Object clone() throws CloneNotSupportedException {  
     return super.clone();  
 }  
  • 为什么调用父类的clone() 就可以实现创建一个一样状态的新对象呢?
    是因为Object.clone() 方法有一个默认实现:

    Creates and returns a copy of this object. The precise meaning of “copy” may depend on the class of the object. –jdk1.7


意思是: 哪个对象调用了这个方法就创建和返回这个对象的一份复制.
  • 深拷贝:
public class Body implements Cloneable{  
    public Head head;  
    public Body() {}  
    public Body(Head head) {this.head = head;}  

    @Override 
    public Object clone() throws CloneNotSupportedException {  
        Body newBody =  (Body) super.clone();  
        newBody.head = (Head) head.clone(); //深拷贝
        return newBody;  
    }  

} 
### C++ 多态场景下的拷贝构造函数 在C++中,当涉及到多态时,拷贝构造函数的行为变得尤为重要。为了理解这一点,考虑以下几种情况: #### 基本概念回顾 - **拷贝构造函数的作用**包括创建对象副本、值传递以及容器操作[^1]。 - 当处理继承层次结构中的对象时,特别是涉及多态的情况下,直接使用默认的浅拷贝可能会导致切片问题——即派生类特有的部分被截断。 #### 示例分析 假设有一个基类`Person`及其派生类`Student`,其中定义了一个虚函数用于展示购票行为,并且实现了协变特性来允许不同的返回类型[^2]。 ```cpp class Person { public: virtual ~Person() {} virtual Person* BuyTicket() const { std::cout << "Person:买票-全价" << std::endl; return new Person(); } }; class Student : public Person { public: virtual Student* BuyTicket() const override { std::cout << "Student:买票-半价" << std::endl; return new Student(); } protected: // 模拟一些额外的数据成员 int m_studentID; private: // 自定义拷贝构造函数防止切片问题 Student(const Student& other) : Person(other), m_studentID(other.m_studentID) {} friend class PersonFactory; // 只有特定工厂可以访问此构造器 }; ``` 这里需要注意的是,在上述代码片段中,虽然显示了如何通过自定义拷贝构造函数避免切片问题,但在实际应用中通常不会公开此类构造函数给所有用户;而是采用其他机制(如工厂模式)控制对象创建过程。 对于多态环境中正确地执行深拷贝,推荐做法之一就是利用虚拟克隆方法(`clone`)替代传统的拷贝构造函数: ```cpp #include <iostream> using namespace std; // 抽象基类提供纯虚 clone 方法支持动态分配内存并复制整个对象图谱 class Human { public: virtual ~Human() = default; /// @brief 实现深拷贝所需的接口 virtual Human *clone() const = 0; virtual void printInfo() const = 0; }; /// 子类具体化其父级声明的方法 class Student final : public Human { public: explicit Student(int id):m_id{id} {}; [[nodiscard]] Human *clone() const override{ return new Student(*this); } void printInfo() const override { cout << "I'm a student with ID:" << this->m_id << endl; } private: int m_id{}; }; int main(){ auto johnson=new Student{98765}; // 动态实例化子类对象 // 利用 clone 函数安全地完成深层复制 unique_ptr<Human> copyOfJohnson(johnson->clone()); johnson->printInfo(); // 输出原对象信息 copyOfJohnson->printInfo(); // 验证新对象是否独立于旧版本 delete johnson; // 清理资源 } ``` 这段程序展示了如何借助 `clone()` 成员函数实现更灵活可靠的深拷贝逻辑,从而绕过了传统上可能遇到的各种陷阱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值