#include<iostream> using namespace std; /* *类内部的private protected public 影响的访问权限 *继承中的private protected public 影响的是父类中的成员在子类中的访问权限的 问题 这个访问权限包括两部分。1.在子类中 2.在子类对象中。 *99%情况下只是用public继承方式。 * *为什么这么说呢,假设我现在有个类 里面有个成员是public pub,protected成员 *pro,private成员 pri。我public继承之后,你以前是public的,还是public,你是 *private,你在子类里面就变成不可访问的了,你是protected还是protected。 * * 你如果是protected继承的话,你父类中的public在子类中就变成了protected, * 你的protected变成了protected,但是你的private还是跟上面一样的,不能访问 * * * 你如果是private继承的话,他public和protected都变成private了,这就说明你在子类内部还是可以访问,但是private还是不能访问 */ /*所以说 * public 提供传承接口用的。因为你public传承下去,public和protected都可以被传承下去, * privatre 提供隐藏数据用的。中间还有一个protected,protected可以隐藏数据还能传承数据。 class Base { public: int pub; protected: int pro; private: int pri; }; class Deriver:private Base { public: void dis() { pro=100; pub=200; } int x; protected: int y; protected: int z; }; int main() { /*1.这样肯定会报错,因为这个y,z都是被保护的数据 Deriver a; a.x=100; a.y=100; a.z=100; */ }
#include<iostream> using namespace std; class Student { public: Student(string sn,int ia,float fs) :name(sn),age(ia),score(fs) { } void dis() { cout<<name<<endl; cout<<age<<endl; cout<<score<<endl; } private: string name; int age; float score; }; class Graduate:public Student { public: Graduate(string sn,int i,float fs,double sa=1000) :Student(sn,i,fs),salary(sa) { } /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/ /*因为子类会调用父类的构造器*/ Graduate(const Graduate &another) { } void display() { dis(); cout<<salary<<endl; } private: double salary; }; int main() { Student s("zhaosi",34,150); s.dis(); Graduate g("nengge",40,200); //g.display(); Graduate f(g); f.display(); }
#include<iostream> using namespace std; class Student { public: Student(string sn,int ia,float fs) :name(sn),age(ia),score(fs) { } Student(const Student & another) { this->name=another.name; this->age=another.age; this->score=another.score; } void dis() { cout<<name<<endl; cout<<age<<endl; cout<<score<<endl; } private: string name; int age; float score; }; class Graduate:public Student { public: Graduate(string sn,int i,float fs,double sa) :Student(sn,i,fs),salary(sa) { } /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/ /*因为子类会调用父类的构造器*/ /*子类未实现拷贝构造的时候,会调用父的拷贝构造器(无论实现与否) * 这句话的理解就是你可以把子类graduate的拷贝拷贝构造器注释掉 * 不会报错 * 子类一旦实现了拷贝构造,则必须显示的父类的拷贝构造器*/ Graduate(const Graduate &another) :Student(another) { /*赋值兼容(子类对象(引用或者指针),可以赋给父类对象(引用或指针) * 这里其实发生了隐式类型转换*/ //这里只会拿前面3个空间拷贝过去*/ /*这里不能放在这里,因为拷贝构造器是不能被继承的 Student(another);*/ this->salary=another.salary
#include<iostream> using namespace std; class Student { public: Student(string sn,int ia,float fs) :name(sn),age(ia),score(fs) { } Student(const Student & another) { this->name=another.name; this->age=another.age; this->score=another.score; } Student &operator=(const Student & another) { this->name=another.name; this->age=another.age; this->score=another.score; return *this; } void dis() { cout<<name<<endl; cout<<age<<endl; cout<<score<<endl; } private: string name; int age; float score; }; class Graduate:public Student { public: Graduate(string sn,int i,float fs,double sa) :Student(sn,i,fs),salary(sa) { } /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/ /*因为子类会调用父类的构造器*/ /*子类未实现拷贝构造的时候,会调用父的拷贝构造器(无论实现与否) * 这句话的理解就是你可以把子类graduate的拷贝拷贝构造器注释掉 * 不会报错 * 子类一旦实现了拷贝构造,则必须显示的父类的拷贝构造器*/ Graduate(const Graduate &another) :Student(another) { /*赋值兼容(子类对象(引用或者指针),可以赋给父类对象(引用或指针) * 这里其实发生了隐式类型转换*/ //这里只会拿前面3个空间拷贝过去*/ /*这里不能放在这里,因为拷贝构造器是不能被继承的 Student(another);*/ this->salary=another.salary; } Graduate & operator=(Graduate &another) { if(this==&another) return *this; else { /*但是这里operator=这个父子类重名*/ Student::operator=(another); this->salary=another.salary; } return *this; } void display() { dis(); cout<<salary<<endl; } private: double salary; }; int main() { Student s("zhaosi",34,150); s.dis(); Graduate g("nengge",40,200,1000); //g.display(); Graduate f(g); Graduate gg("11",1,1,1); /*第一步:这里没问题,前面没有显示写出赋值运算符重载的时候,说明这里 * 面含有默认*/ /*第二步:我们实现父类的运算符重载 * 子类中未实现赋值重载时,会调用父类的赋值重载(无论实现与否) * 子类一旦实现赋值重载,不会调用父类的赋值重载了。 * Student & operator=(const Student& another)*/ gg=f; f.display(); gg.display(); }
#include<iostream> using namespace std; class Father { public: void dis() { } }; class Son:public Father { public: void dis() { /*我这里的逻辑是我这里的dis调用父类的dis,父子类重名就会出现 * shadow,shadow就是阴影的意思,就是子类中会把父类重名成员给shadow掉 覆盖之后他就认为父类中没有这个东西了,这里他就会自己调用自己。 所以它会一直递归下去,没有尽头。 dis(); shadow只跟函数名有关,跟你有没有参数没有关系,跟返回值没关 你int dis()和void dis()是一样的,你int dis(int) 和int dis()也是一样的 */ /*所以这个时候只能用命名空间*/ Father::dis(); } }; int main() { }
#include<iostream> using namespace std; /* *重载:发生在同一个作用域,函数名相同,参数列表不同 * 参数列表不同包括个数,类型和顺序。有一个或一个以上满足都会构成重载 *shadow:发生在父子类中,爷爷类和孙子类之间也可以。只要函数名相同即可构成shadow。 *一般来说,重载是我们希望看到的,因为重载可以给我们带来很多方便。但是shadow是我们不希望发生的,尽量不要写shadow重名函数。发生了需要用命名空间来解决这个问题 * */ int main() { }