栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 第三章 继承

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 第三章 继承

继承

叫一声爸爸,开启财富之门

class Animal {
public:
	string name() {return this->name;}
private:
	string name;
};
class Cat : public Animal{};

类与类之间的关系,在Animal中所有的属性和方法都包含在猫类中.
Cat是子类(派生类)
Animal是父类(基类)

继承-子类访问权限


当子类无论是这哪三个,都可以访问父类中的public, 与private;

它所影响的是外部对子类的访问权限–>

继承-对外的访问权限

子类从父类继承过来的权限对外的权限;

影响的外部对于子类继承父类的方法与属性的权限,这些方法与属性权限只能被压低不能被提升
子类继承过来的对外

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

class Animal {
public :
    Animal(){}
    Animal(string name, int age) : __name(name), age(age) {}
    void say() {
        cout << "my name is " << __name  << ", my age is " << age << endl;
    }

protected:
    string __name;


private:
    int age;
};


class Cat : public Animal{
public :
    Cat() = delete;
    Cat(string name, int age) : Animal(name, age){}
};

class Bat : protected Animal{
public: 
    Bat() = delete;
    Bat(string name, int age) : Animal(name, age){}
    void say() {
        this->Animal::say();
        cout << "class Bat : " << __name << endl;
        //cout << "class age : " << age <
    Cat a("kitty", 29);
    a.say();
    Bat b("fong", 16384);
    b.say();//不能直接访问say();
    return 0;
}

继承-构造函数

调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;


class D {
public :
    D() {cout << "D constructor" << endl;}
    ~D() {
        cout << "D destructor" << endl;
    }
};

class A {
public :
    A() = delete;
    A(int x, int y) {cout << "A constructor" << endl;}
    ~A() {
        cout << "A destructor" << endl;
    }
};

class B {
    public :
    B() {cout << "B constructor" << endl;}
    ~B() {
        cout << "B destructor" << endl;
    }
    
};

class C : public D{
public :
    C() : a(3, 4) {cout << "C constructor" << endl;}
    ~C() {
        cout << "C destructor" << endl;
    }
private:
    B b; 
    A a;
};

int main() {
    C c;
    return 0;
}
菱形继承

所以才引出:允许一个实体类,多个接口类
指代不明

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

struct A{
    int x;
};

struct B : virtual public A{//解决菱形继承的问题使用virtual
    void set(int x) {
        this->x = x;
        cout << "set :" << &this->x << endl;
    }
};


struct C : virtual public A{
    int get() {
        cout << "get : " << &this->x << endl;
        return this->x;
    }
};

struct D : public B, public C{};

int main() {
    D d;
    cout << sizeof(d) << endl;
    d.set(9973);
    cout << d.get() << endl;
    return 0;
}
24
set :0x7fffc89da2c0
get : 0x7fffc89da2c0
9973

解决方法用virtual, 合并产生冲突的父亲类

继承下的拷贝构造

拷贝构造函数 : 显示调用父类拷贝构造函数
赋值运算符 : 显示调用父类的赋值运算函数

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;


class A {
public :
    A() {
        cout << "class A constuctor" << endl;
        this->x = 0x01020304;
    }
    A(const A &a) {
        cout << "class A copy constuctor : "<< this << endl;
    }
    int x;
};


class B : public A {
    
public :
    B() {
        this->y = 0x05060708;
        cout << "class B constuctor" << endl;
    }
    B(const B &b) : A(b) {
        cout <<  "class B copy constuctor : " << this << endl;
    }
    int y;
};

int main() {
    B b1;
    B b2(b1);
    const char *msg = (const char *)(&b1);
    for(int i = 0; i < sizeof(B); i++) {
        printf("%X", msg[i]);
    }
    
    return 0;
}
string的简单实现
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

namespace haizei {

class string {
public :
    string() {
        this->__buff_size = 10;
        this->buff = new char[this->__buff_size];
        this->__length = 0;
    }
    string(const char *str) {
        this->__buff_size = strlen(str) + 1;
        this->buff = new char[this->__buff_size];
        strcpy(this->buff, str);
        this->__length = this->__buff_size - 1;
    }
    char &at(int ind) {
        if(ind < 0 || ind >= __length) {
            cout << "String Error : out of range" << endl;
            return __end;
        }
        return this->operator[](ind);
    }
    char &operator[](int ind) {
        return buff[ind];
    }
    const char *c_str() const {
        return buff;
    }
    string operator+(const string &s) {
        int size = this->__length + s.__length + 1;
        char *temp = new char[size];
        strcpy(temp, this->buff);
        strcat(temp, s.buff);
        return temp;
    }
    int size() {return this->__length;}
private:
    int __length, __buff_size;
    char *buff;
    char __end;
};

}

ostream &operator<<(ostream &out, const haizei::string &s) {
    out << s.c_str() << endl;
    return out;
}


int main() {
    haizei::string s1 = "hello world", s2 = ", haizei", s3 = "harbin.";
    cout << s1 << endl;
    s1[3] = '6';
    cout << s1 << endl;
    cout << s1 + s2 + s3 <
       cout << s1[i] << endl; 
    }
    return 0;
}
子类向父类转换

子类的引用和指针都可以隐式转换为父类的引用和指针。所以在这个例子里面,cat、pCat、animal和pAnimal都代表同一个对象。只要你修改了cat.name、pCat->name、animal.name或者pAnimal->name的其中一个,那么另外的三个会同时被改变。

父类向子类转换

想象一下你获得了一个Animal* pAnimal;,你怎么知道他到底是Cat还是Dog呢?C++ 的dynamic_cast就可以帮到你。当然使用这个功能的前提是,Animal类(或者他的父类——如果有的话)必须至少要包含一个virtual函数

当然你也可以使用static_cast。它跟dynamic_cast的区别就是,他不回去检查pAnimal到底是不是Cat,就直接转换给你。如果不是的话,你就会拿到一个野指针,使用它就会发生 undefined behavior。

另外要提到的是,dynamic_cast也可以在父类的几个子类下转换,如果不返回nullptr就代表你的转换成功了,这个指针指向的的确是你需要的类型的对象。而static_cast这样做会有语法错误。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021767.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号