Day7知识点:
1.类的继承,是新的类从已有类那里得到已有的特性;类的派生,从已有类产生新类的过程。原有的类称为基类或父类,产生的新类称为派生类或子类。
C++通过继承,来实现代码的重用性。
继承的实验代码:
#include <iostream>
using namespace std;
#if 0
Inherit&Derive
学生 姓名,年龄,性别,学号,吃饭,学习
老师 姓名,年龄,性别,工号,吃饭,教学
姓名,年龄,性别,吃饭 父类 基类
继承 派生
学生:学号,学习 老师:工号,教学 子类 派生类;
#endif
class Human //父类 共性
{
public:
void eat(string food)
{
cout<<"I am eating"<<food<<endl;
}
};
class Student:public Human //子类 是在父类的基础上增加新的功能,体现的是共性
{
public:
void study(string course)
{
cout<<"I am a student , I am learning"<<course<<endl;
}
};
class Teacher:public Human
{
public:
void tech(string course)
{
cout<<"I am a teacher , I am teaching"<<course<<endl;
}
};
int main()
{
Student s;
s.study("c++");
s.eat("黄焖鸡米饭");
Teacher t;
t.tech("c++");
t.eat("新疆大盘鸡");
return 0;
}
2.关系定性is-a,has-a
is-a
狗是一种动物,动物是狗的基类,狗是动物的派生类。
A是B,B是A的基类,A是B的派生类。为继承关系。
has-a
车有方向盘和轮胎,方向盘和轮胎是车的组成部分。
A包含B,B是A的组成部分。为聚合关系。
2.派生类的声明语法
class Son:public Father
{
public:
int pub;
void func()
{
x = 3;
y = 4;
z = 5;
}
protected:
int pro;
private:
int pri;
};
3.第一个public为继承方式,第二个public为访问权限
继承方式public没有影响 子类的访问方式
影响了父类成员在子类的访问方式:
继承方式为公有继承public:在子类内,public和protected是可以访问的(通过子类函数),private不可访问(inaccess);
:子类对象(子类外),只有public的可以访问。
假设father中有三种访问权限pub,pro,pri,在子类中分别为public,protected,inacess
public继承实验代码:
#include <iostream>
using namespace std;
class Father
{
public:
int x;
protected:
int y;
private:
int z;
};
class Son:public Father
{
public:
int pub;
void func()
{
x = 3;
y = 4;
// z = 5;
}
protected:
int pro;
private:
int pri;
};
//
int main()
{
Son s;
s.x = 0;
// s.y = 0;
// s.z = 0;
return 0;
}
4.派生类对基类的接收
1.全盘接收,除了构造器与析构器。可能造成派生类成员冗余,基类需要设计;
2.派生类有自己的个性才有意义。
5.派生类构造函数
Graduate::Graduate(string sn, int ia, float fs, double ds)
:Student(sn,ia,fs),salary(ds)
{
}
class Father
{
public:
Father(int i){}
};
class Son:public Father
{
public:
Son():Father(4){}
};
派生类中如果有标配,重载或者默认,派生类中构造函数可以不用显示调用基类的构造器
class Father
{
public:
Father(){}
};
class Son:public Father
{
public:
Son(){}
};
子类只需对父类负责,不需要对父类的父类负责,父类的父类,由父类负责。
class Father
{
public:
Father(int i){}
};
class Son:public Father
{
public:
Son(int j):Father(4){}
};
class Grandson:public Son
{
public:
Grandson():Son(5){}
};
class A
{
public:
A()
{
cout<<"A"<<endl;
}
};
class Father
{
public:
Father(int i)
{
cout<<"Father"<<endl;
}
};
class Son:public Father
{
public:
Son(int j):Father(4)
{
cout<<"Son"<<endl;
}
};
class Grandson:public Son
{
public:
Grandson(int k):Son(5)
{
cout<<"Grandson"<<endl;
}
A a;
};
实验代码:
实验代码太长,在此不上传,代码文件名为 InheritSomeFunc
6.
a) 赋值兼容:子类对象(引用或指针),可以赋给父类对象(引用或指针)
b)子类未实现拷贝构造时,会默认调动父类的拷贝构造器。若子类有拷贝构造器,则必须显示调用父类拷贝构造器(因为继承不会继承构造器)。
c)子类中未实现赋值重载时,会调用父类的赋值重载(无论实现会未实现)。若子类实现了赋值重载,不会主动调用父类的赋值重载。
d) 子类中会把父类重名的成员shadow掉,函数名同即可构成shadow,与参数和返回值无关。
若非重名不可,则必须加上作用域运算符
#include <iostream>
using namespace std;
class Father
{
public:
void dis()
{
}
};
class Son:public Father
{
public:
void dis()
{
/*Father::*/dis();
}
};
int main()
{
Son son;
son.dis();
return 0;
}
实验代码:
//graduate.h
#ifndef GRADUATE_H
#define GRADUATE_H
#include "student.h"
class Graduate:public Student
{
public:
Graduate(string sn, int ia, float fs,double ds);
Graduate(const Graduate &another);
Graduate& operator =(const Graduate &another);
void print();
private:
float salary;
};
#endif // GRADUATE_H
//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
Student(string sn,int ia,float score);
Student(const Student& another);
Student& operator =(const Student& another);
void dis();
private:
string name;
int age;
float score;
};
#endif // STUDENT_H
//graduate.cpp
#include "graduate.h"
Graduate::Graduate(string sn, int ia, float fs,double ds)
:Student(sn,ia,fs),salary(ds)
{
}
Graduate::Graduate(const Graduate &another)
:Student(another),salary(another.salary)
{
}
Graduate& Graduate::operator =(const Graduate &another)
{
if(this == &another)
return *this;
Student::operator =(another); //虽然继承父类的重载函数过来了,但由于命名冲突,不
//能直接用,必须加命名空间
this->salary = another.salary;
return *this;
}
void Graduate::print()
{
dis();
cout<<"salary:"<<salary<<endl;
}
//student.cpp
#include "student.h"
#include <iostream>
using namespace std;
Student::Student(string sn , int ia,float fs)
:name(sn),age(ia),score(fs)
{
}
Student::Student(const Student& another)
{
name = another.name;
age = another.age;
score = another.score;
}
Student& Student::operator =(const Student& another)
{
if(this == &another)
return *this;
this->name = another.name;
this->age = another.age;
this->score = another.score;
}
void Student::dis()
{
cout<<"name:"<<name<<endl;
cout<<"age:"<<age<<endl;
cout<<"score:"<<score<<endl;
}
//main.cpp
#include <iostream>
#include "student.h"
#include "graduate.h"
extern int x=1;
using namespace std;
int main()
{
Student s("zhaosi",34,150);
s.dis();
cout<<"-----------------------"<<endl;
Graduate g("nengge",35,150,1200);
g.print();
cout<<"-----------------------"<<endl;
Graduate gg("nhoioi",1,1,1);
gg.print();
gg = g;
gg.print();
return 0;
}
7.派生类析构顺序与构造顺序相反,子类->成员->基类。
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"A()"<<endl;
}
~A()
{
cout<<"~A()"<<endl;
}
};
class Base
{
public:
Base()
{
cout<<"Base()"<<endl;
}
~Base()
{
cout<<"~Base()"<<endl;
}
};
class Derive:public Base
{
public:
Derive()
{
cout<<"Drive()"<<endl;
}
~Derive()
{
cout<<"~Derive()"<<endl;
}
private:
A a;
};
int main()
{
Derive d;
return 0;
}
8.
overload重载,同一作用域,函数名相同,参数列表不同(个数,类型,顺序)
shadow发生在父子类中,只要函数名相同,即可构成shadow
9.派生类的友元函数
实验代码:
#include <iostream>
using namespace std;
class Student
{
public:
Student(int a, int b):
_a(a),_b(b){}
friend ostream &operator<<(ostream & out, Student & stu);
private:
int _a;
int _b;
};
ostream &operator<<(ostream & out, Student & stu)
{
out<<stu._a<<"--"<<stu._b<<endl;
return out;
}
class Graduate:public Student
{
public:
Graduate(int a, int b, int c)
:Student(a,b),_c(c){}
friend ostream &operator<<(ostream & out, Graduate & gra);
private:
int _c;
};
ostream &operator<<(ostream & out, Graduate & gra)
{
cout<<static_cast<Student&>(gra);
cout<<gra._c<<endl;
return out;
}
int main()
{
Student s(1,2);
cout<<s;
Graduate g(3,4,5);
cout<<g;
}
10.继承方式
public public public
pub pub pub pub
pro pro pro pro
pri inaccess inaccess inaccess
protected protected protected
pub pro pro pro
pro pro pro pro
pri inaccess inaccess inaccess
private private private
pub pri inaccess inaccess
pro pri inaccess inaccess
pri inaccess inaccess inaccess
#include <iostream>
using namespace std;
class Base
{
public:
int pub;
protected:
int pro;
private:
int pri;
};
class Derive:/*public*//*protected*/private Base
{
public:
void func()
{
// pub = 100;
// pro = 100;
pub = 100;
}
};
int main()
{
Derive d;
// d.pub = 100;
return 0;
}
//bed.h
#ifndef BED_H
#define BED_H
#include <iostream>
using namespace std;
class Bed
{
public:
Bed();
void sleep();
};
#endif // BED_H
//sofa.h
#ifndef SOFA_H
#define SOFA_H
#include <iostream>
using namespace std;
class Sofa
{
public:
Sofa();
void sit();
};
#endif // SOFA_H
//sofabed.h
#ifndef SOFABED_H
#define SOFABED_H
#include "sofa.h"
#include "bed.h"
class SofaBed:public Sofa,public Bed
{
public:
SofaBed();
};
#endif // SOFABED_H
//bed.cpp
#include "bed.h"
Bed::Bed()
{
}
void Bed::sleep()
{
cout<<"go to bed and have a sleep"<<endl;
}
//sofa.cpp
#include "sofa.h"
Sofa::Sofa()
{
}
void Sofa::sit()
{
cout<<"have a seat and have a sleep"<<endl;
}
//sofabed.cpp
#include "sofabed.h"
SofaBed::SofaBed()
{
}
//main.cpp
#include <iostream>
#include "sofa.h"
#include "bed.h"
#include "sofabed.h"
using namespace std;
int main()
{
Sofa sf;
sf.sit();
Bed bed;
bed.sleep();
SofaBed sb;
sb.sit();
sb.sleep();
}
12.虚继承
将基类中的共同成员提取出来,只保留一份共同成员,在内存中只有基类成员的一份拷贝,被提取出来共同继承的类称为虚基类.
//funiture.h
#ifndef FUNITURE_H
#define FUNITURE_H
class Funiture
{
public:
Funiture(float len, float wi, float we);
void discript();
protected:
float len;
float wid;
float weight;
};
#endif // FUNITURE_H
//bed.h
#ifndef BED_H
#define BED_H
#include <iostream>
#include "funiture.h"
using namespace std;
class Bed:virtual public Funiture
{
public:
Bed(float len, float wi, float we);
void sleep();
};
#endif // BED_H
//sofa.h
#ifndef SOFA_H
#define SOFA_H
#include <iostream>
#include "funiture.h"
using namespace std;
class Sofa:virtual public Funiture
{
public:
Sofa(float len, float wi, float we);
void sit();
};
#endif // SOFA_H
//sofabed.h
#ifndef SOFABED_H
#define SOFABED_H
#include "sofa.h"
#include "bed.h"
#include "funiture.h"
class SofaBed:public Sofa,public Bed
{
public:
SofaBed(float len, float wi, float we);
};
#endif // SOFABED_H
//funiture.cpp
#include "funiture.h"
#include <iostream>
using namespace std;
Funiture::Funiture(float len, float wi, float we)
:len(len),wid(wi),weight(we)
{
}
void Funiture::discript()
{
cout<<"len = "<<len<<endl;
cout<<"wid = "<<wid<<endl;
cout<<"weight = "<<weight<<endl;
}
//bed.cpp
#include "bed.h"
Bed::Bed(float len, float wi, float we)
:Funiture(len,wi,we)
{
}
void Bed::sleep()
{
cout<<"go to bed and have a sleep"<<endl;
}
//sofa.cpp
#include "sofa.h"
Sofa::Sofa(float len, float wi, float we)
:Funiture(len,wi,we)
{
}
void Sofa::sit()
{
cout<<"have a seat and have a sleep"<<endl;
}
//sofabed.cpp
#include "sofabed.h"
SofaBed::SofaBed(float len, float wi, float we)
:Funiture(len,wi,we),Bed(len,wi,we),Sofa(len,wi,we)
{
}