C++深度解析教程笔记12
- 第43课 - 继承的概念和意义
- 实验-类的组合
- 实验-类的继承
- 实验-子类与父类的构造顺序
- 小结
- 第44课 - 继承中的访问级别
- 实验-子类直接访问父类非公成员(error)
- 实验-子类访问父类非公成员protected
- 实验-复杂的例子
- bug
- 小结
- 第45课 - 不同的继承方式
- 实验-例子
- 实验-3种继承的对比
- 实验-多种语言分析
- 小结
- 第46课 - 继承中的构造与析构
- 实验-默认调用
- 实验-显示调用
- 实验-析构顺序
- 小结
- 第47课 - 父子间的冲突
- 实验-子类与父类的同名变量
- 实验-区分子类与父类的同名变量
- 实验-子类函数覆盖父类同名函数
- 小结
- 第48课 - 同名覆盖引发的问题
- 实验-父类赋值给子类
- 实验-函数重写
- 小结
第43课 - 继承的概念和意义
实验-类的组合
#include <iostream>
#include <string>
using namespace std;
class Memory
{
public:
Memory()
{
cout << "Memory()" << endl;
}
~Memory()
{
cout << "~Memory()" << endl;
}
};
class Disk
{
public:
Disk()
{
cout << "Disk()" << endl;
}
~Disk()
{
cout << "~Disk()" << endl;
}
};
class CPU
{
public:
CPU()
{
cout << "CPU()" << endl;
}
~CPU()
{
cout << "~CPU()" << endl;
}
};
class MainBoard
{
public:
MainBoard()
{
cout << "MainBoard()" << endl;
}
~MainBoard()
{
cout << "~MainBoard()" << endl;
}
};
class Computer
{
Memory mMem;
Disk mDisk;
CPU mCPU;
MainBoard mMainBoard;
public:
Computer()
{
cout << "Computer()" << endl;
}
void power()
{
cout << "power()" << endl;
}
void reset()
{
cout << "reset()" << endl;
}
~Computer()
{
cout << "~Computer()" << endl;
}
};
int main()
{
Computer c;
return 0;
}
/*
Memory()
Disk()
CPU()
MainBoard()
Computer()
~Computer()
~MainBoard()
~CPU()
~Disk()
~Memory()
*/
实验-类的继承
#include <iostream>
#include <string>
using namespace std;
class Parent
{
int mv;
public:
Parent()
{
cout << "Parent()" << endl;
mv = 100;
}
void method()
{
cout << "mv = " << mv << endl;
}
};
class Child : public Parent
{
public:
void hello()
{
cout << "I'm Child calss!" << endl;
}
};
int main()
{
Child c;
c.hello();
c.method();
return 0;
}
/*
Parent()
I'm Child calss!
mv = 100
*/
实验-子类与父类的构造顺序
#include <iostream>
#include <string>
using namespace std;
class Memory
{
public:
Memory()
{
cout << "Memory()" << endl;
}
~Memory()
{
cout << "~Memory()" << endl;
}
};
class Disk
{
public:
Disk()
{
cout << "Disk()" << endl;
}
~Disk()
{
cout << "~Disk()" << endl;
}
};
class CPU
{
public:
CPU()
{
cout << "CPU()" << endl;
}
~CPU()
{
cout << "~CPU()" << endl;
}
};
class MainBoard
{
public:
MainBoard()
{
cout << "MainBoard()" << endl;
}
~MainBoard()
{
cout << "~MainBoard()" << endl;
}
};
class Computer
{
Memory mMem;
Disk mDisk;
CPU mCPU;
MainBoard mMainBoard;
public:
Computer()
{
cout << "Computer()" << endl;
}
void power()
{
cout << "power()" << endl;
}
void reset()
{
cout << "reset()" << endl;
}
~Computer()
{
cout << "~Computer()" << endl;
}
};
class HPBook : public Computer
{
string mOS;
public:
HPBook()
{
mOS = "Windows 8";
}
void install(string os)
{
mOS = os;
}
void OS()
{
cout << mOS << endl;
}
};
class MacBook : public Computer
{
public:
void OS()
{
cout << "Mac OS" << endl;
}
};
int main()
{
HPBook hp;
hp.power();
hp.install("Ubuntu 16.04 LTS");
hp.OS();
cout << endl;
MacBook mac;
mac.OS();
return 0;
}
/*
Memory()
Disk()
CPU()
MainBoard()
Computer()
power()
Ubuntu 16.04 LTS
Memory()
Disk()
CPU()
MainBoard()
Computer()
Mac OS
~Computer()
~MainBoard()
~CPU()
~Disk()
~Memory()
~Computer()
~MainBoard()
~CPU()
~Disk()
~Memory()
*/
小结
第44课 - 继承中的访问级别
实验-子类直接访问父类非公成员(error)
#include <iostream>
#include <string>
using namespace std;
class Parent
{
private:
int mv;
public:
Parent()
{
mv = 100;
}
int value()
{
return mv;
}
};
class Child : public Parent
{
public:
int addValue(int v)
{
mv = mv + v; // ???? 如何访问父类的非公有成员 error: 'int Parent::mv' is private within this context
}
};
int main()
{
return 0;
}
实验-子类访问父类非公成员protected
#include <iostream>
#include <string>
using namespace std;
class Parent
{
protected:
int mv;
public:
Parent()
{
mv = 100;
}
int value()
{
return mv;
}
};
class Child : public Parent
{
public:
void addValue(int v)
{
mv = mv + v; //子类使用父类protected成员变量
}
};
int main()
{
Parent p;
cout << "p.mv = " << p.value() << endl;//p.mv = 100
// p.mv = 1000; // error
Child c;
cout << "c.mv = " << c.value() << endl;//c.mv = 100 子类返回父类protected成员变量
c.addValue(50);
cout << "c.mv = " << c.value() << endl;//c.mv = 150
// c.mv = 10000; // error: 'int Parent::mv' is protected within this context
return 0;
}
实验-复杂的例子
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Object
{
protected:
string mName;
string mInfo;
public:
Object()
{
mName="Object";
mInfo="";
}
string GetName()
{
return mName;
}
string GetInfo()
{
return mInfo;
}
};
class Point:public Object
{
private:
int mx;
int my;
public:
Point(int x=0,int y=0)
{
mx=x;
my=y;
ostringstream s;
mName="point";
s<<"P("<<mx<<","<<my<<")";
mInfo=s.str();
}
int x()
{
return mx;
}
int y()
{
return my;
}
};
class Line:public Object
{
private:
Point mp1;
Point mp2;
public:
Line(Point p1,Point p2)
{
mp1=p1;
mp2=p2;
ostringstream s;
mName="Line";
s<<"Line from "<<mp1.GetInfo()<<" to "<<mp2.GetInfo();//mp2.GetInfo() .mInfo
mInfo=s.str();
}
Point linestart()
{
return mp1;
}
Point lineend()
{
return mp2;
}
};/*
*/
int main()
{
Object o;
Point p1(1,2);
Point p2(3,4);
Line L1(p1,p2);/**/
cout<<"o.GetName():"<<o.GetName()<<endl;
cout << "o.GetInfo():"<<o.GetInfo() << endl;
cout << endl;
cout << p1.GetName() << endl;
cout << p1.GetInfo() << endl;
cout << endl;
cout << L1.GetName() << endl;
cout << L1.GetInfo() << endl;
return 0;
}
/*
o.GetName():Object
o.GetInfo():
point
P(1,2)
Line
Line from P(1,2) to P(3,4)*/
bug
s<<"Line from "<<mp1.GetInfo()<<" to "<<mp2.mInfo;//mp2.GetInfo() .mInfo//error: 'std::string Object::mInfo' is protected|位置在父类的定义位置
小结
第45课 - 不同的继承方式
实验-例子
#include <iostream>
#include <string>
using namespace std;
class Parent
{
};
class Child_A : public Parent
{
};
class Child_B : protected Parent
{
};
class Child_C : private Parent
{
};
int main()
{
return 0;
}
实验-3种继承的对比
#include <iostream>
#include <string>
using namespace std;
class Parent
{
protected:
int m_a;
protected:
int m_b;
public:
int m_c;
void set(int a, int b, int c)
{
m_a = a;
m_b = b;
m_c = c;
}
};
class Child_A : public Parent
{
public:
void print()
{
cout << "m_a" << m_a <<" "
<< "m_b" << m_b <<" "
<< "m_c" << m_c << endl;
}
};
class Child_B : protected Parent
{
public:
void print()
{
cout << "m_a" << m_a <<" "
<< "m_b" << m_b <<" "
<< "m_c" << m_c << endl;
}
};
class Child_C : private Parent
{
public:
void print()
{
cout << "m_a" << m_a << " "
<< "m_b" << m_b << " "
<< "m_c" << m_c << endl;
}
};
int main()
{
Child_A a;
Child_B b;
Child_C c;
a.m_c = 100;
//b.m_c = 100; // Child_B 保护继承自 Parent, 所以所有的 public 成员全部变成了 protected 成员, 因此外界无法访问 error: 'int Parent::m_c' is inaccessible within this context
//c.m_c = 100; // Child_C 私有继承自 Parent, 所以所有的成员全部变成了 private 成员, 因此外界无法访问error: 'int Parent::m_c' is inaccessible within this context
a.set(1, 1, 1);
//b.set(2, 2, 2);//error: 'Parent' is not an accessible base of 'Child_B'
//c.set(3, 3, 3);//error: 'Parent' is not an accessible base of 'Child_C'
a.print(); //m_a1 m_b1 m_c1
// b.m_a = 100;// error: 'int Parent::m_a' is protected within this context
b.print(); //m_a2 m_b0 m_c14639008
c.print(); //m_a0 m_b8 m_c0
return 0;
}
实验-多种语言分析
在这里插入代码片
gdc 45-3.d
./a.out
gmcs 45-3.cs
/45-3.exe
javac 45-3.java
java program
小结
第46课 - 继承中的构造与析构
子类对象的构造子类中
可以定义构造函数子类构造函数
一必须对继承而来的成员进行初始化
·直接通过初始化列表或者赋值的方式进行初始
调用父类构造函数进行初始化
实验-默认调用
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
Parent()
{
cout << "Parent()" << endl;
}
Parent(string s)
{
cout << "Parent(string s) : " << s << endl;
}
};
class Child : public Parent
{
public:
Child()
{
cout << "Child()" << endl;
}
Child(string s) : Parent(s)//不能丢
{
cout << "Child(string s) : " << s << endl;
}
};
int main()
{
Child c; //Child() Parent() 不对
Child cc("cc"); // Parent(string s) :cc Child(string s) :cc
return 0;
}
/*
Parent()
Child()
Parent(string s) : cc
Child(string s) : cc */
对象创建时构造函数的调用顺序 1.
调用父类的构造函数 2.
调用成员变量的构造函数 3.调用类自身的构造函数
口诀心法:
先父母,后客人,再自己,
实验-显示调用
#include <iostream>
#include <string>
using namespace std;
class Object
{
public:
Object(string s)
{
cout << "Object(string s) : " << s << endl;
}
};
class Parent : public Object
{
public:
Parent() : Object("Default")
{
cout << "Parent()" << endl;
}
Parent(string s) : Object(s)
{
cout << "Parent(string s) : " << s << endl;
}
};
class Child : public Parent
{
Object mO1;
Object mO2;
public:
Child() : mO1("Default 1"), mO2("Default 2")
{
cout << "Child()" << endl;
}
Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2")
{
cout << "Child(string s) : " << s << endl;
}
};
int main()
{
Child cc("cc");
return 0;
}
//先父母
//Object(string s) :cc
//Parent(string s) : cc
//再客人
//Object(string s) :cc1
//Object(string s) :cc2
//自己
//Child(string s) :cc
/*
Object(string s) : cc
Parent(string s) : cc
Object(string s) : cc 1
Object(string s) : cc 2
Child(string s) : cc
*/
实验-析构顺序
#include <iostream>
#include <string>
using namespace std;
class Object
{
string ms;
public:
Object(string s)
{
cout << "Object(string s) : " << s << endl;
ms = s;
}
~Object()
{
cout << "~Object() : " << ms << endl;
}
};
class Parent : public Object
{
string ms;
public:
Parent() : Object("Default")
{
cout << "Parent()" << endl;
ms = "Default";
}
Parent(string s) : Object(s)
{
cout << "Parent(string s) : " << s << endl;
ms = s;
}
~Parent()
{
cout << "~Parent() : " << ms << endl;
}
};
class Child : public Parent
{
Object mO1;
Object mO2;
string ms;
public:
Child() : mO1("Default 1"), mO2("Default 2")
{
cout << "Child()" << endl;
ms = "Default";
}
Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2")
{
cout << "Child(string s) : " << s << endl;
ms = s;
}
~Child()
{
cout << "~Child() " << ms << endl;
}
};
int main()
{
Child cc("cc");
cout << endl;
return 0;
}
//Object(string s) :cc
//Parent(string s) :cc
//Object(string s) :cc 1
//Object(string s) :cc 2
//Child(string s) : cc
//~Child() cc
//~Object() :cc 2
//~Object() :cc 1
//~Parent() :cc
//~Object() :cc
小结
第47课 - 父子间的冲突
实验-子类与父类的同名变量
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
int mi;
};
class Child : public Parent
{
public:
int mi;
};
int main()
{
Child c;
c.mi = 100; // mi 究竟是子类自定义的,还是从父类继承得到的?
return 0;
}
实验-区分子类与父类的同名变量
#include <iostream>
#include <string>
using namespace std;
namespace A
{
int g_i = 0;
}
namespace B
{
int g_i = 1;
}
class Parent
{
public:
int mi;
Parent()
{
cout << "Parent() : " << "&mi = " << &mi << endl;
}
};
class Child : public Parent
{
public:
int mi;
Child()
{
cout << "Child() : " << "&mi = " << &mi << endl;
}
};
int main()
{
Child c;
c.mi = 100;
c.Parent::mi = 1000;
cout << "&c.mi = " << &c.mi << endl;
cout << "c.mi = " << c.mi << endl;
cout << "&c.Parent::mi = " << &c.Parent::mi << endl;
cout << "c.Parent::mi = " << c.Parent::mi << endl;
return 0;
}
/*
Parent() : &mi = 0x61fe18
Child() : &mi = 0x61fe1c
&c.mi = 0x61fe1c
c.mi = 100
&c.Parent::mi = 0x61fe18
c.Parent::mi = 1000
*/
实验-子类函数覆盖父类同名函数
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
int mi;
void add(int v)
{
mi += v;
}
void add(int a, int b)
{
mi += (a + b);
}
};
class Child : public Parent
{
public:
int mi;
void add(int v)
{
mi += v;
}
void add(int a, int b)
{
mi += (a + b);
}
void add(int x, int y, int z)
{
mi += (x + y + z);
}
};
int main()
{
Child c;
c.mi = 100;
c.Parent::mi = 1000;
cout << "c.mi = " << c.mi << endl;
cout << "c.Parent::mi = " << c.Parent::mi << endl;
c.add(1);//子类
c.add(2, 3);//子类
c.add(4, 5, 6);//子类
//c.Parent::add(2, 3);调用父类函数
cout << "c.mi = " << c.mi << endl;//
cout << "c.Parent::mi = " << c.Parent::mi << endl;
//c.mi = 100
//c.Parent::mi = 1000
//c.mi = 121
//c.Parent::mi = 1000
return 0;
}
小结
第48课 - 同名覆盖引发的问题
实验-父类赋值给子类
用子类初始化父类
父类引用子类
父类指向子类
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
int mi;
void add(int i)
{
mi += i;
}
void add(int a, int b)
{
mi += (a + b);
}
};
class Child : public Parent
{
public:
int mv;
void add(int x, int y, int z)
{
mv += (x + y + z);
}
};
int main()
{
Parent p;
Child c;
p = c;//子类赋值给父类
Parent p1(c);
Parent& rp = c;//定义父类引用子类
Parent* pp = &c;
rp.mi = 100;
rp.add(5); // c的引用 的add预计报错 没有发生同名覆盖?
rp.add(10, 10); // 没有发生同名覆盖?
/* 为什么编译不过? */
//pp->mv = 1000;//error: 'class Parent' has no member named 'mv'; did you mean 'mi'?
//pp->add(1, 10, 100);// error: no matching function for call to 'Parent::add(int, int, int)'
return 0;
}
实验-函数重写
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
int mi;
void add(int i)
{
mi += i;
}
void add(int a, int b)
{
mi += (a + b);
}
void print()
{
cout << "I'm Parent." << endl;
}
};
class Child : public Parent
{
public:
int mv;
void add(int x, int y, int z)
{
mv += (x + y + z);
}
void print()
{
cout << "I'm Child." << endl;
}
};
//void how_to_print(Child* p)//error: invalid conversion from 'Parent*' to 'Child*' [-fpermissive]
void how_to_print(Parent* p)//父类指针
{
p->print();
}
int main()
{
Parent p;
Child c;
how_to_print(&p); // Expected to print: I'm Parent.
how_to_print(&c); // Expected to print: I'm Child.
return 0;
}
//I'm Parent.
//I'm Parent.