zoukankan      html  css  js  c++  java
  • 设计模式:原型模式(C++)【克隆羊多莉】

    转载:https://blog.csdn.net/qq_29542611/article/details/79521841

    原型模式介绍

    这节我们继续学习设计模式——原型模式。我们先看看原型模式的标准说法,用原型实例指定创建对象的种类并且通过拷贝这些原型创建新的对象。其实原型模式就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节而已。

    我们先看看C++和其他一些面向对象的编程语言的区别。在java、C# 或者一些其他的面向对象编程语言,他们所有的类都是都会继承或者间接继承Object类。比如说java中Object类 有一个clone方法,实现上就是原型模式的体现,子类需要根据情况进行实现罢了。而我们的C++呢 没有Object(上帝类),所以呢 我们需要在我们自己的原型类中添加一个clone 克隆方法就行了。有人或许会说,C++不是有拷贝构造函数么。确实有默认的拷贝构造函数呀,但是 默认的拷贝构造函数只提供基本的值拷贝,如果有在堆区开辟空间的成员呢?所以我们要提供自己的拷贝构造函数进行深拷贝,方便用户,还应该提供一个clone方法(实际就是去调用拷贝构造函数)。下面看原型模式克隆羊多莉 案例。

    克隆羊多利代码实现

    原型图就是不画了吧,就一个类。。。。对外提供clone方法,如果类成员有在堆区开辟空间,需要重新拷贝构造函数进行深拷贝!clone方法本质还是调用拷贝构造函数。注意,我们的析构函数要释放堆区开辟的内容哟。

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
     
    class Sheep
    {
        friend ostream& operator<<(ostream&, Sheep& sheep);
    public:
        //构造函数
        Sheep(char* name,int age)
        {
            this->age = age;
            this->name = new char[strlen(name) + 1]{ 0 };
            strcpy(this->name, name);
        }
        //拷贝构造函数
        Sheep(const Sheep& sheep)
        {
            this->age = sheep.age;
            this->name = new char[strlen(sheep.name) + 1]{ 0 };
            strcpy(this->name, sheep.name);
        }
        ~Sheep()
        {
            if (name != NULL)
            {
                delete name;
            }
        }
        //重载 = 赋值运算符
        Sheep& operator=(const Sheep& sheep)
        {
            //1、防止自身赋值
            if (this == &sheep)
            {
                return *this;
            }
            //2、释放原来在堆空间开辟的空间
            if (this->name != NULL)
            {
                delete this->name;
                this->name = NULL;
            }
            //3、执行深拷贝
            this->age = sheep.age;
            this->name = new char[strlen(sheep.name) + 1]{ 0 };
            strcpy(this->name, sheep.name);
        }
        Sheep* clone()
        {
            //直接调用 拷贝构造函数,因为拷贝构造函数已经做了深拷贝的动作。
            return new Sheep(*this);
        }
        
        char* getName()
        {
            return name;
        }
        void setName(char* name)
        {
            if (this->name != NULL)
            {
                delete this->name;
                this->name = NULL;
            }
            this->name = new char[strlen(name) + 1]{ 0 };
            strcpy(this->name, name);
     
        }
        int getAge()
        {
            return age;
        }
        void setAge(int age)
        {
            this->age = age;
        }
    private:
        char* name;
        int age;
    };
    //重载<<运算符
    ostream& operator<<(ostream&, Sheep& sheep)
    {
        cout << "[name = " << sheep.name << " ,age = "<< sheep.age << "]";
        return cout;
    }
     
    int main(int argc, char *argv[])
    {
        Sheep* sheep1 = new Sheep("多利",0);
        Sheep* sheep2 = sheep1->clone();
        cout << "sheep1:" << *sheep1 << endl;
        cout << "sheep2:" << *sheep2 << endl;
        cout << "删除克隆原型sheep1" << endl;
        delete sheep1;
        cout << "sheep2:" << *sheep2 << endl;
     
        return EXIT_SUCCESS;
    }

    运行结果

  • 相关阅读:
    【剑指offer】和为S的连续整数序列
    【剑指offer】连续子数组最大和
    【剑指offer】从尾到头打印链表
    【Spark】概述
    【剑指offer】题目20 顺时针打印矩阵
    【剑指offer】题目36 数组中的逆序对
    【C语言】二维数组做形参
    【剑指offer】题目38 数字在排序数组中出现的次数
    SAP 锁对象 基本概念与基本操作 SE11
    线程特定数据TSD总结
  • 原文地址:https://www.cnblogs.com/Toya/p/14063438.html
Copyright © 2011-2022 走看看