#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()
{
}