-
C++第五天
今天继续讲多继承,主要讲了继承的构造顺序和菱形继承以及虚函数和动态多态,还讲了异质链表。今天讲的派生类和基类的赋值着实是把我绕晕了,尤其是到了后面又出现了指针,直接就是晕着过去的。老师还让我们写一下异质链表当作作业,结果还是写不出来。今天终于将项目一做出来了,虽然有些瑕疵(比如在输入的时候不小心会段错误),但是该有的功能都有了,可以运行了,后期慢慢修改瑕疵就好了。
c++中空类大小是1
继承的构造顺序(先基类后本身)
用哪个生成对象,哪个就是最派生类
构造顺序:先是被虚继承的基类,然后是正常继承的基类,最后是本身
函数模板是静态多态
动态多态:直到运行到的时候才知道用哪个动作
cpu最小执行单元是线程
#include <iostream>
#include <string>
using namespace std;
//菱形问题使用虚继承来解决
class People
{
public:
People(){cout << "People()\n";}
People(string id, string name, string born, string addr)
: m_strId(id), m_strBorn(born)
{
m_strName = name;
m_strAddr = addr;
cout << "People(...)\n";
}
void info()
{
cout << "name:" << m_strName << " addr:" << m_strAddr << endl;
}
string m_strName;
private:
const string m_strId;
const string m_strBorn;
string m_strAddr;
};
//虚继承
//系统会自动生成一个虚继承表
//类中会自动生成一个指针
//该指针指向虚继承表
//该类可以通过虚继承表间接的访问虚继承的基类的数据
class Student: virtual public People
{
public:
//继承过来的基类数据的初始化必须在派生类中的初始化列表中
//调用基类的构造函数来初始化
//若没有调用,则默认调用基类的无参构造函数来初始化
Student(){cout << "Student()\n";}
Student(string id, string name, string born, string addr, string stuid, float score)
: People(id, name, born, addr)
{
m_strStuId = stuid;
m_fScore = score;
cout << m_strName << endl;
cout << "Student(...)\n";
}
private:
string m_strStuId;
float m_fScore;
};
//被虚继承的基类由最派生类真正继承
//被虚继承的基类数据由最派生类负责初始化
//在最派生类的初始化列表中调用基类的构造函数进行初始化,
//若没有调用则默认调用基类的无参构造函数初始化
class Teacher: virtual public People
{
public:
Teacher(){cout << "teacher()\n";}
Teacher(string id, string name, string born, string addr, string level, float salary)
: People(id, name, born, addr)
{
m_strLevel = level;
m_fSalary = salary;
cout << "Teacher(...)\n";
}
private:
string m_strLevel;
float m_fSalary;
};
//构造顺序:1,被虚继承的基类2,正常继承的类3,本身构造函数体
class GS: public Student, public Teacher
{
public:
GS(){cout << "GS()\n";}
GS(string id, string name, string born, string addr, string stuid, float score, string level, float salary, string degree)
: Student(id, name, born, addr, stuid, score)
, Teacher(id, name, born, addr, level, salary)
, m_strDegree(degree), People(id, name, born, addr)
{
cout << "GS(...)\n";
}
private:
string m_strDegree;
};
int main(void)
{
cout << "people:" << sizeof(People) << endl;
cout << "stu:" << sizeof(Student) << endl;
cout << "tec:" << sizeof(Teacher) << endl;
cout << "gs:" << sizeof(GS) << endl;
//GS gs;
GS gs("1001", "zhangsan", "1990-01-12", "shanghai", "stu_001", 89, "讲师", 8000, "化学研究生");
//gs.Student::info();
//gs.Teacher::info();
gs.info();
return 0;
}
#include <iostream>
using namespace std;
class Shape
{
public:
Shape(){}
float area(){return 0;}
};
class Square: public Shape
{
public:
Square(float w=0): m_fWidth(w)
{}
float area()
{
return m_fWidth*m_fWidth;
}
private:
float m_fWidth;
};
class Triangle: public Shape
{
public:
Triangle(float b=0, float h=0)
{
m_fBottom = b;
m_fHight = h;
}
private:
float m_fBottom;
float m_fHight;
};
int main(void)
{
Shape shape;
Square sq(34);
cout << "shape:" << shape.area() << " square:" << sq.area()<<endl;
//派生类对象可以赋给基类的对象,反过来则不行
// shape = sq;
// cout << shape.area() << endl;
// sq = shape; // X
return 0;
}
#include <iostream>
using namespace std;
class Shape
{
public:
Shape(){}
float area()
{
cout << "Shape::area()\n";
return 0;
}
};
class Square: public Shape
{
public:
Square(float w=0): m_fWidth(w)
{}
float area()
{
cout << "Square::area()\n";
return m_fWidth*m_fWidth;
}
private:
float m_fWidth;
};
class Triangle: public Shape
{
public:
Triangle(float b=0, float h=0)
{
m_fBottom = b;
m_fHight = h;
}
private:
float m_fBottom;
float m_fHight;
};
int main(void)
{
Shape shape;
Square sq(34);
cout << "shape:" << shape.area() << " square:" << sq.area()<<endl;
//指针调用函数时受限于类型
Shape *pshape = &sq;
pshape->area();
//派生类对象的地址可以赋给基类的指针反过来则不行
//Square *psquare = &shape; // X
return 0;
}
#include <iostream>
using namespace std;
class Shape
{
public:
Shape(){}
//虚函数
//若类中存在虚函数
//则程序运行时系统会自动生成一张虚函数表,表中存放类的虚函数的入口地址
//类中会自动添加一个指针
//该指针指向虚函数表
//即该指针存放了虚函数表的地址
//称之为虚函数表指针
virtual float area()
{
cout << "Shape::area()\n";
return 0;
}
};
class Square: public Shape
{
public:
Square(float w=0): m_fWidth(w)
{}
//若派生类中存在和基类虚函数A函数原型相同的函数B,则该B函数默认为虚函数
//用派生类中的B函数入口地址覆盖掉虚函数表中的基类A虚函数的地址
float area()
{
cout << "Square::area()\n";
return m_fWidth*m_fWidth;
}
private:
float m_fWidth;
};
class Triangle: public Shape
{
public:
Triangle(float b=0, float h=0)
{
m_fBottom = b;
m_fHight = h;
}
float area()
{
cout << "Triangle::area()\n";
return m_fBottom*m_fHight/2;
}
private:
float m_fBottom;
float m_fHight;
};
void show(Shape *pshape)
{
//通过指针调用函数时
//若该函数是虚函数,则到虚函数表中查找该函数的入口地址,进而执行
cout << pshape->area() << endl;
}
int main(void)
{
cout << "shape:" << sizeof(Shape) << " square:" << sizeof(Square) << " triangle:" << sizeof(Triangle) << endl;
#if 0
Shape shape;
Square sq(4);
Triangle tri(3, 4);
show(&shape);
show(&sq);
show(&tri);
#endif
return 0;
}
//上面有一段代码与之相同,这一段在继承时没有用virtual;
#include <iostream>
#include <string>
using namespace std;
class People
{
public:
People(){cout << "People()\n";}
People(string id, string name, string born, string addr)
: m_strId(id), m_strBorn(born)
{
m_strName = name;
m_strAddr = addr;
cout << "People(...)\n";
}
void info()
{
cout << "name:" << m_strName << " addr:" << m_strAddr << endl;
}
private:
const string m_strId;
string m_strName;
const string m_strBorn;
string m_strAddr;
};
class Student: public People
{
public:
//继承过来的基类数据的初始化必须在派生类中的初始化列表中调用基类的构造函数来初始化
//若没有调用,则默认调用基类的无参构造函数来初始化
Student(){cout << "Student()\n";}
Student(string id, string name, string born, string addr, string stuid, float score)
: People(id, name, born, addr)
{
m_strStuId = stuid;
m_fScore = score;
cout << "Student(...)\n";
}
private:
string m_strStuId;
float m_fScore;
};
class Teacher: public People
{
public:
Teacher(){cout << "teacher()\n";}
Teacher(string id, string name, string born, string addr, string level, float salary)
: People(id, name, born, addr)
{
m_strLevel = level;
m_fSalary = salary;
cout << "Teacher(...)\n";
}
private:
string m_strLevel;
float m_fSalary;
};
class GS: public Student, public Teacher
{
public:
GS(){cout << "GS()\n";}
GS(string id, string name, string born, string addr, string stuid, float score, string level, float salary, string degree)
: Student(id, name, born, addr, stuid, score)
, Teacher(id, name, born, addr, level, salary)
, m_strDegree(degree)
{
cout << "GS(...)\n";
}
private:
string m_strDegree;
};
int main(void)
{
cout << "people:" << sizeof(People) << endl;
cout << "stu:" << sizeof(Student) << endl;
cout << "tec:" << sizeof(Teacher) << endl;
cout << "gs:" << sizeof(GS) << endl;
//GS gs;
GS gs("1001", "zhangsan", "1990-01-12", "shanghai", "stu_001", 89, "讲师", 8000, "化学研究生");
gs.Student::info();
//gs.Teacher::info();
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class People
{
public:
People(){cout << "People()\n";}
People(string id, string name, string born, string addr)
: m_strId(id), m_strBorn(born)
{
m_strName = name;
m_strAddr = addr;
cout << "People(...)\n";
}
void info()
{
cout << "name:" << m_strName << " addr:" << m_strAddr << endl;
}
protected:
string m_strPhone;
private:
const string m_strId;
string m_strName;
const string m_strBorn;
string m_strAddr;
};
//class Student: public People
//class Student: protected People
//class Student: People
class Student: private People
{
public:
//继承过来的基类数据的初始化必须在派生类中的初始化列表中调用基类的构造函数来初始化
//若没有调用,则默认调用基类的无参构造函数来初始化
Student(){cout << "Student()\n";}
Student(string id, string name, string born, string addr, string stuid, float score)
: People(id, name, born, addr)
{
m_strStuId = stuid;
m_fScore = score;
//cout << m_strName << endl; // X
cout << m_strPhone << endl;
cout << "Student(...)\n";
}
#if 0
void info()
{
}
#endif
void test()
{
info();
//cout << m_strPhone << endl;
// cout << m_strName << endl;
}
private:
string m_strStuId;
float m_fScore;
};
int main(void)
{
Student s("101011", "zhangsan", "1900-10-10", "shanghai", "stu-001", 89);
s.test();
//s.info();
//cout << s.m_strName << endl;// X
//cout << s.m_strPhone << endl; // X
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class People
{
public:
People(){}
People(string id, string name)
: m_strId(id), m_strName(name)
{}
virtual void info()
{
cout << "id:" << m_strId << " name:" << m_strName << endl;
}
private:
string m_strId;
string m_strName;
};
class Student: public People
{
public:
Student(){}
Student(string id, string name, float score)
: People(id, name)
{
m_fScore = score;
}
void info()
{
People::info();
cout << "score:" << m_fScore << endl;
}
private:
float m_fScore;
};
class Teacher: public People
{
public:
Teacher(){}
Teacher(string id, string name, string level, float salary)
: People(id, name)
{
m_strLevel = level;
m_fSalary = salary;
}
void info()
{
People::info();
cout << "level:" << m_strLevel << " salary:" << m_fSalary << endl;
}
private:
string m_strLevel;
float m_fSalary;
};
class Node
{
public:
Node(People *people)
{
m_people = people;
m_next = NULL;
}
People *m_people;
Node *m_next;
};
class Link
{
public:
Link()
{
m_pFirstNode = NULL;
m_iLen = 0;
}
void insert(People *people)
{
Node *node = new Node(people);
node->m_next = m_pFirstNode;
m_pFirstNode = node;
m_iLen++;
}
void show()
{
Node *node = m_pFirstNode;
while (NULL != node)
{
node->m_people->info();
node = node->m_next;
}
}
private:
Node *m_pFirstNode;
int m_iLen;
};
int main(void)
{
Link link;
link.insert(new People("100102", "zhangsan"));
link.insert(new Student("1019e01", "lisi", 89));
link.insert(new Teacher("1829e11", "kongzi", "jiaoshou", 89090));
link.show();
cout << "Hello World" << endl;
return 0;
}
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a=90)
: m_j(a), m_i(m_j)
{}
//普通成员变量的初始化顺序和在初始化列表中的顺序无关,和申明定义的顺序保持一致
int m_i;
int m_j;
};
int main(void)
{
Test t(190);
cout << t.m_i << ' ' << t.m_j << endl;
return 0;
}
#include <iostream>
using namespace std;
class A
{
public:
A(){cout << "A()\n";}
~A(){cout << "~A()\n";}
};
class B
{
public:
B(){cout << "B()\n";}
~B(){cout << "~B()\n";}
};
//多继承情况下,基类的构造顺序和在初始化列表中调用基类构造函数的先后顺序无关,与继承的先后顺序保持一致,谁写在前面先构造谁
class Test: public A, public B
{
public:
Test()
: B(), A()
{cout << "Test()\n";}
~Test()
{cout << "~Test()\n";}
};
int main(void)
{
Test t;
return 0;
}
#include <iostream>
using namespace std;
#define PI 3.14
class Circle
{
public:
Circle(float radius)
: m_fRadius(radius)
{
cout << "Circle(...)" << endl;
}
virtual float area()
{
cout << "Circle::area()" << endl;
return PI*m_fRadius*m_fRadius;
}
virtual float volume()
{
cout << "Circle::volume()" << endl;
return 0;
}
float getRadius()
{
return m_fRadius;
}
private:
float m_fRadius;
};
class Sphere: public Circle
{
public:
Sphere(float radius): Circle(radius)
{
cout << "Sphere(...)" << endl;
}
virtual float area()
{
cout << "Sphere::area()" << endl;
//4PI*R*R
return 4*PI*getRadius()*getRadius();
}
virtual float volume()
{
cout << "Sphere::volume()" << endl;
float radius = getRadius();
return PI*radius*radius*radius*4/3;
}
private:
};
class Column: public Circle
{
public:
Column(float radius, float h)
: Circle(radius)
{
m_fHight = h;
cout << "Column(...)" << endl;
}
virtual float area()
{
cout << "Column::area()" << endl;
float radius = getRadius();
return PI*radius*radius*2 + 2*PI*radius*m_fHight;
}
virtual float volume()
{
cout << "Column::volume()" << endl;
float radius = getRadius();
return PI*radius*radius*m_fHight;
}
private:
float m_fHight;
};
void show(Circle &circle)
{
cout << circle.area() << ' ' << circle.volume() << endl;
}
int main(void)
{
Sphere sphere(2);
show(sphere);
Column column(2, 5);
show(column);
return 0;
}