【C++笔记】十三、代码重用(上)

1.valarray模板类

2.成员变量的初始化顺序

3.C++中的单件模式(Singleton)

4.explicit与单参数的构造方法

5.私有(private)继承

6.避免操作符重载造成的递归调用

7.保护(protected)继承

8.使用using重新定义访问权限

9.C++中的多继承

10.多继承与共同基类的问题

11.虚基类(虚继承)

12.多继承与父类方法冲突


1.valarray模板类

#include <iostream>
#include <valarray>
using namespace std;
int main(int argc, const char * argv[]) {

    // valarray模板类
    valarray<int> array1{20,30,40};
    cout << array1.size() << endl;  // 3
    cout << array1.sum() << endl;   // 90
    cout << array1.max() << endl;   // 40
    
    valarray<int> array2{60,70,80};
    array1.swap(array2);    // 两个数组所有元素进行交换
    cout << array2[1] << endl;   // 30
    
    valarray<int> array3{10};
    array1.swap(array3);
    cout << array1.size() << endl;   // 1
    cout << array3.size() << endl;   // 3 
    
   return 0;
}

2.成员变量的初始化顺序

#include <iostream>
using namespace std;

class MyClass
{
public:
    int code1;
    int code2;
    //MyClass() : code1(20), code2(code1)  // 父类可以在构造方法后面初始化成员变量,code2是20,先初始化code1,在初始化code2
    MyClass() : code2(30), code1(code2) // 在构造方法后面初始化成员变量时,初始化顺序和变量的前后顺序无关,和变量的定义顺序有关
    {
        //cout << code2 << endl;
        cout << code1 << endl;  // 0 code2默认值是0
    }
};

int main(int argc, const char * argv[]) {
    // 成员变量的初始化顺序
    MyClass myClass;
    return 0;
}

3.C++中的单件模式(Singleton)

#include <iostream>
using namespace std;

class SingletonClass
{
private:
    int mCode;
    static SingletonClass* instance; // 定义了一个静态指针,指向SingletonClass类型的对象,用于检测SingletonClass类是否被定义,如果未被定义,则instance为空指针
    SingletonClass()
    {
        
    }
    SingletonClass(int code)
    {
        mCode = code;
    }
public:
    static SingletonClass* getInstance()
    {
        if(instance == nullptr)
        {
            instance = new SingletonClass();
        }
        return instance;
    }
    static SingletonClass* getInstance(int code)  // 重载
    {
        if(instance == nullptr)
        {
            instance = new SingletonClass(code);  // 这里调用了private里的构造方法SingletonClass
        }
        return instance;
    }
    string getName()
    {
        return "Bill";
    }
};

SingletonClass* SingletonClass::instance = nullptr; // 类的静态变量要在类的外部进行初始化,这里的前面是调用了构造方法,构造了一个指向SingletonClass的指针

int main(int argc, const char * argv[]) {
    // 单件模式(Singleton),获得一个类的唯一实例
    //  1.  不能使用new创建对象,也不能直接定义类变量————放到private里面
    //  2.  至少需要提供一个静态的方法,用于返回唯一的对象实例
    
    SingletonClass* instance1 = SingletonClass::getInstance();  // ::的效果和->应该是一样的
    cout << instance1->getName() << endl;   // Bill

    SingletonClass* instance2 = SingletonClass::getInstance(123); // 这里123不会传给mCode,因为instance在之前已经被定义,不为空了,在if判断时不再成立
    if(instance1 == instance2)
    {
        cout << "instance1 == instance2" << endl; // 二者是相等的,因为instance2没有另外new空间
    }
   // SingletonClass *singletonClass = new SingletonClass();
    
    return 0;
}

4.explicit与单参数的构造方法

#include <iostream>
using namespace std;

class Integer
{
private:
    int mValue;
public:
    // 构造方法不需要返回数值
    explicit Integer(int value)  
    {
        mValue = value;
    }
    int getValue()
    {
        return mValue;
    }
};

int main(int argc, const char * argv[]) {
    // explicit与构造方法
    //Integer n = 20;  //加了explicit后这句话会报错,如果不加,这句话的作用就相当于Integer n = Integer(20);
    Integer n = Integer(20);  // Integer(20)
    cout << n.getValue() << endl; // 20
    return 0;
}

5.私有(private)继承

#include <iostream>
using namespace std;

class ParentClass
{
private:
    int mCode = 20;
public:
    int getCode()
    {
        return mCode;
    }
};

class ParentClass1
{
private:
    int mCode1 = 20;
public:
    int getCode1()
    {
        return mCode1;
    }
};

class SubClass : private ParentClass,private ParentClass1   // 私有继承
{ 
public:
    int code = getCode();
    
    ParentClass& getParentClass()  // 返回引用
    {
        return *this;
    }
};

int main(int argc, const char * argv[]) {
    // 公有继承中,在子类中可以使用父类public的方法、变量,且这些方法、变量在子类中也是public,可以在类外访问
    // 私有继承,父类中所有public内容在子类中都相当于potected类型,只能在子类中访问,不能在外部访问
    SubClass subClass;
   // cout << subClass.getCode() << endl;
    cout << subClass.code << endl;  // 20,code是subClass自己的public值
    cout << subClass.getParentClass().getCode() << endl;  // 20,这里如果直接用subClass.getCode()会报错,因为是私有继承,getCode()是父类的方法,在子类相当于protect类型,在外部不能调用,而经由getParentClass()后,用this指针返回了父类,所以就可以使用getCode()了
    return 0;
}

6.避免操作符重载造成的递归调用

#include <iostream>
using namespace std;

class String
{
private:
    string mStr = "hello";
public:
    friend ostream& operator<<(ostream& os, const String& str); // 设置操作符重载函数为友元函数,可以访问私有类型变量
};

ostream& operator<<(ostream& os, const String& str)  // 对输出流操作符进行重载
{
    return os << str.mStr;
}

class NewString : public String
{
    
};

ostream& operator<<(ostream& os, const NewString& str)
{
    return os << "NewString:" << (String&)str;  // 这里str为子类,需要转换为父类,否则会无限的递归,循环的加载重载后的“<<”操作符,不停的打印:NewString:
}

int main(int argc, const char * argv[]) {
    // 避免操作符重载造成的递归调用
    NewString newString;
    cout << newString << endl; // 这里会调用重载后的“<<”操作符,打印:NewString:hello
    return 0;
}

7.保护(protected)继承

#include <iostream>
using namespace std;
class ParentClass
{
private:
    int mCode = 20;
public:
    int getCode()
    {
        return mCode;
    }
};

class SubClassPrivate : private ParentClass
{
public:
    int code = getCode();  // 继承来的父类的东西都变成私有的了,外部没有办法访问,即,如果再有一个子类,去继承SubClassPrivate ,那么是没法用getCode()的
};

class SubClassProtected : protected ParentClass
{
    // 如果再有一个子类,去继承SubClassProtected ,还可以访问getCode()
};

class MyClass1 : public SubClassProtected
{
public:
    int code = getCode();
};
class MyClass2 : public SubClassPrivate
{
public:
    //int code = getCode(); // 报错
};

int main(int argc, const char * argv[]) {

    // 保护(protected)继承,在衍生出第三代类的时候,会有区别
    return 0;
}

8.使用using重新定义访问权限

#include <iostream>
using namespace std;

class ParentClass
{
private:
    int mCode = 50;
public:
    int code = 10;
    int getCode()
    {
        return 30;
    }
    int operator[](string key)  // 操作符重载
    {
        if(key == "code")
        {
            return code;
        }
        else
        {
            return -1;
        }
    }
};

class SubClass : private ParentClass  // 私有继承
{
public:
    // 这里想在外部访问父类内容还有一种方法,就是在本子类定义一个方法,return父类的内容
    using ParentClass::code;  // 这样使用using之后就能在外部使用该父类内容了
    using ParentClass::getCode; // 对于函数使用using时,不需要写返回值类型啥的
    using ParentClass::operator[];
   // using ParentClass::mCode;    // using是无法将父类中原本的私有成员转换成public的
};

int main(int argc, const char * argv[]) {

    // 使用using重新定义访问权限
    SubClass subClass;
    cout << subClass.getCode() << endl; // 30 
    cout << subClass.code << endl;      // 10
    cout << subClass["code"] << endl;   // 10
    cout << subClass["abc"] << endl;    // -1
    return 0;
}

9.C++中的多继承

#include <iostream>
using namespace std;

class Person
{
public:
    string name;
    int age;
};

ostream& operator<<(ostream& os, Person& person) // 重载 输出Person类的操作符
{
    return os << "姓名:" << person.name << " 年龄:" << person.age;
}

class Teacher
{
public:
    int code;
    string school;
    string specialty;
};
ostream& operator<< (ostream& os, Teacher& teacher) // 重载 输出Teacher类的操作符
{
    return os << "职工编号:" << teacher.code << " 学校:" << teacher.school << " 专业:" << teacher.specialty;
}

class Professor:public Person, public Teacher // 多继承
{
public:
    string title;
};
ostream& operator<<(ostream& os, Professor& professor) // 重载 输出Professor类的操作符
{
    return os << (Person&)professor << endl << (Teacher&)professor << endl << "职称:" << professor.title;
}  // (Person&)professor是输出professor所具有的Person相对应的属性,(Teacher&)professor同理

int main(int argc, const char * argv[]) {
    // 多继承(multiple inheritance,MI)
    Professor p;
    p.name = "王军";
    p.age = 40;
    p.code = 25;
    p.school = "清华大学";
    p.specialty = "计算机";
    p.title = "教授";
    
    cout << p << endl;
    
    return 0;
}

 

10.多继承与共同基类的问题

#include <iostream>
using namespace std;

class BaseClass
{

};

class ParentClass1 : public BaseClass
{

};

class ParentClass2 : public BaseClass  // ParentClass2 与 ParentClass1 有共同基类
{

};

class SubClass : public ParentClass1, public ParentClass2  // 多继承
{

};

int main(int argc, const char * argv[]) {
    // 虚继承(虚基类)
    SubClass* subClass = new SubClass(20);
    BaseClass* baseClass = (ParentClass1*)subClass;  //可以通过这样的方式指定一下父类,就可以划等号了
    // BaseClass* baseClass = subClass;   // 会报错,因为subClass继承了两个baseClass的内容,所以二者不能这样划等号
    return 0;
}

11.虚基类(虚继承)

#include <iostream>
using namespace std;

class BaseClass
{
private:
    int mValue1;
public:
    BaseClass(int value1)   // 构造方法,如果不定义,则有一个默认的没有参数的构造方法
    {
        mValue1 = value1;
        cout << "BaseClass" << endl;
    }
};

class ParentClass1 : virtual public BaseClass // BaseClass 是ParentClass1 的虚基类
{
private:
    int mValue2;
public:
    ParentClass1(int value2) : BaseClass(value2)  // 子类构造方法 调用了父类的构造方法
    {
        mValue2 = value2;
        cout << "ParentClass1" << endl;
    }
};

class ParentClass2 : public virtual BaseClass
{
private:
    int mValue2;
public:
    ParentClass2(int value2) : BaseClass(value2)
    {
        mValue2 = value2;
        cout << "ParentClass2" << endl;
    }
};

class SubClass : public ParentClass1, public ParentClass2 
{
private:
    int mValue;
public:
    SubClass(int value) : BaseClass(value),ParentClass1(value), ParentClass2(value)
    {
        mValue = value;
    }
};

int main(int argc, const char * argv[]) {
 // 虚继承(虚基类)
    SubClass* subClass = new SubClass(20);
 // subClass的父类定义了虚基类,此时就可以划等号了,
 // C++编译器会自动选取一个父类的基类给subClass继承,而不是有几个父类,就继承几个BaseClass
    BaseClass* baseClass = subClass;  // 调用了一次BaseClass(通过subClass直接调用的祖先类),
// 一次ParentClass1(通过subclass调用的父类,但是这个父类在调用他的父类时,发现使用的是虚继承,前面已经调用了一次Basecalss的内容了,所以在此不再调用Baseclass),
// 一次ParentClass2(和ParentClass2同理)
    return 0;
}

12.多继承与父类方法冲突

#include <iostream>
using namespace std;

class ParentClass1
{
protected:
    virtual void show()
    {
        cout << "ParentClass1" << endl;
    }
};

class ParentClass2
{
protected:
    virtual void show()
    {
        cout << "ParentClass2" << endl;
    }
};

class SubClass : public ParentClass1, public ParentClass2  // 多继承,ParentClass1和ParentClass2都有一个show方法,所以在SubClass调用show方法时,要注意冲突问题
{
public:

   /* void show()
    {
        ParentClass1::show();
        cout << "SubClass" << endl;
    }*/

    void show1()
    {
        ParentClass1::show();
    }
    void show2()
    {
        ParentClass2::show();
    }
};

int main(int argc, const char * argv[]) {

    // 多继承与父类方法冲突    
    SubClass subClass;
    subClass.show1();
    subClass.show2();
   // ParentClass1 *parentClass1 = new SubClass();
   // parentClass1->show();  // 此句结合上句,调用的是SubClass中的show(因为subclass中的show方法覆盖了parentClass1中的show方法),subclass中没有show方法时,且parentClass1中的show是public类时,调用parentClass1中的show

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DUANDAUNNN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值