C++第五天学习

时间:2022-07-02 18:21:38

回顾:
1.友元 friend

2.运算符重载

类型 operator运算符(参数表)

抽象、封装
类是面向对象程序设计中最基本的概念
类的背后隐藏的思想是数据抽象和封装
是进行封装和数据隐藏的工具,它将数据和对数据操作紧密的结合在一起。

定义一个类,定义其数据成员、成员函数的过程称为封装类
------------------------------
1.继承与派生
在C++中,所谓继承就是在一个已存在的类的基础上建立一个新的类,已存在的称为基类(base class)或父类(father class),新建立的类称为派生类(derived class)或子类(son class).

一个新类从已有类那里获得其已有特性,这种现象称为类的继承
从另一个角度说,从已有的类产生一个新类的过程就是类的派生

继承实现了代码的重用。

class person
{
string name;
int age;

};

class student : person
{

float sco;
};

C++派生类的声明方式:
class 派生类名 : [继承方式] 基类名
{
//派生类新增加的成员
};

继承方式:
public
private
protected

2.派生类的构造
派生类的成员包括两个部分:
从基类继承过来的成员
自己增加的成员

构造一个派生类包括以下工作:
1.从基类接收成员
派生类把基类的全部成员(不包括构造函数和析构函数)接收过来

2.调整从基类接收的成员

3.增加自己的特性

3.派生类成员的访问属性
1.基类的成员函数访问基类的成员 可以的
2.派生类的成员函数访问派生类的成员 可以
3.基类的成员函数访问派生类的成员 不可以
4.派生类的成员函数访问基类的成员 ???
5.在派生类内部访问派生类的成员 可以
6.在派生类的外部访问基类的成员 ???

如何确定基类成员在派生类中的访问属性:
要考虑基类成员本身的访问属性
要考虑派生类所声明的对基类的继承方式

不同的继承方式决定了基类成员在派生类的访问属性:
public:公有继承
基类的公有成员和保护成员在派生类中保持原有的访问属性,基类的私有成员仍为基类私有。

private:私有继承
基类的公有成员和保护成员在派生类中成了私有成员,基类的私有成员仍为基类私有
protected:保护继承
基类的公有成员和保护成员在派生类中成了受保护成员,基类的私有成员仍为基类私有。保护成员的意思是,不能被外界访问,但可以被派生类的成员访问。

4.私有继承
私有基类中的成员 在私有派生类中的访问属性 在私有派生类外的访问属性
私有成员 不可访问 不可访问
公有成员 可访问 不可访问
保护成员 可访问 不可访问

由于私有继承限制太多,一般不常用。

5.公有继承
公有基类中的成员 在公有派生类中的访问属性 在公有派生类外的访问属性
私有成员 不可访问 不可访问
公有成员 可访问 可访问
保护成员 可访问 不可访问

最常用的继承方式。

6.保护继承
保护基类中的成员 在保护派生类中的访问属性 在保护派生类外的访问属性
私有成员 不可访问 不可访问
公有成员 可访问 不可访问,但其子类可以访问
保护成员 可访问 不可访问,但其子类可以访问

----------------------------------------------------------------------
总结:
基类中的成员 在公有派生类中 在私有派生类中 在保护派生类中
私有成员 不可访问 不可访问 不可访问
公有成员 公有 私有 保护
保护成员 保护 私有 保护

7.派生类中的构造函数和析构函数
当基类的构造函数没有参数,或者没有显式定义构造函数时,子类可以不向父类传递参数,甚至可不定义构造函数。

当基类含有带参数的构造函数时,子类必须定义构造函数,以提供把参数传递给父类构造函数的途径。

在C++中,子类构造函数的一般形式:
派生类的名(参数总表):基类名(参数)

//派生类新增加的数据成员初始化

在创建派生类对象时,先执行基类的构造函数,再执行派生类的构造函数
在销毁派生对象时,先执行派生类的构造函数,再执行基类的析构函数

8.多重继承(略)

9.函数重写
在子类中定义与父类中原型相同的函数
函数重写只发生在父类与子类之间
父类中被重写的函数依然会继承给子类,默认情况下子类中的函数会隐藏父类中的函数。
通过作用域运算符::访问到父类中被隐藏的函数

10.赋值兼容性原则

基类与派生类对象之间也存在有赋值兼容关系
基类与派生类对象之间的赋值兼容原则:
指在需要基类对象的任何地方,都可以使用 公有派生类 的对象来替代。

具体地说:
1.子类对象可以向父类对象赋值
Child c;
Parent p = c;
2.子类对象可以初始化父类对象的引用
Parent &rp = c;
3.子类对象的地址可以赋值给指向父类对象的指针
Parent *pp = &c;
4.如果函数的形参是父类对象或父类对象的引用,在调用函数时,可用子类对象作为实参。

11.当赋值兼容性原则 遇上 函数重写

12.虚函数
虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数。

虚函数的作用是允许在派生类中重新定义与基类同名(函数原型完全相同)的函数,并且可以通过 基类的 指针 来访问基类和派生类中的同名函数。、

格式:
virtual 函数类型 函数名(参数表)

函数体

13.多态性
多态 的意思是一个事物有多种形态
在面向对象方法中,所谓多态就是不同对象收到相同的消息,产生不同的行为
在C++中,多态性是指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,这样就可以用同一个函数名调用不同内容的函数
也就是说,可以用同样的接口访问功能不同的函数,从而实现 ‘一个接口 多种方法’

多态性分为两类:
静态多态性:静态多态性是通过 函数重载,运算符重载来实现的。
动态多态性:运行时多态性,动态多态性是通过虚函数来实现的。

14.纯虚函数与抽像类

class che
{
public:
virtual stop()=0;

private:
lunzi

};

clas shape
{
virtual area()=0;
};
纯虚函数是一个在基类中说明的虚函数,它在该基类中没有定义,但要求在它的派生类中根据需要对它进行定义,或仍说明为纯虚函数。
声明纯虚函数的一般形式:
virtual 函数类型 函数名(参数表)=0;

包含纯虚函数的类,就是抽象类。
注:抽象类不能用来实例化对象,但是可以定义指向抽象类的指针。

作业:
定义一个点类,以它为父类,派生一个圆类,求圆的面积,然后以圆类为基类,派生一个圆柱,求圆柱的表面积、体积。
然后,重载<<可以用来输出点、圆、圆柱。
约定:
点:Point(x,y);
圆:Circle(x,y,r);
圆柱:cylinder(x,y,r,h);

答案代码

#include<iostream>
#include<cstdio>
using namespace std;

class Point
{
public:
Point(double a,double b)
{
x=a;
y=b;
}
~Point()
{

}
private:
double x;
double y;
};

class Circle:public Point
{
public:
Circle(double a,double b,double c):Point(a,b)
{
r=c;
s=3.14*r*r;
}
double get_s()
{
return s;
}
void show()
{
cout<<s<<endl;
}
friend ostream& operator<<(ostream &o,Circle &c);
~Circle()
{

}
private:
double r;
double s;
};

class Cylinder:public Circle
{
public:
Cylinder(double x1,double y1,double r1,double h1):Circle(x1,y1,r1)
{
h=h1;
ss=get_s();
cy=ss*h;
}
void show1()
{
cout<<cy<<endl;
}
friend ostream& operator<<(ostream &o,Cylinder &cyl);
~Cylinder()
{

}
private:
double h;
double ss;
double cy;
};

ostream& operator<<(ostream &o,Circle &c)
{
o<<c.s;
return o;
}

ostream& operator<<(ostream &o,Cylinder &cyl)
{
o<<cyl.cy;
return o;
}

int main(void)
{
Circle c(0,0,1);
//c.show();
cout<<c<<endl;
Cylinder cy1(0,0,1,2);
//cy.show1();
cout<<cy1<<endl;
return 0;
}

#include<iostream>
using namespace std;

class person
{
public:
void show()
{
cout << name << "," << age << endl;
}
private:
string name;
protected:
int age;

};

class student: protected person
{
public:

void show1()
{
show();
// cout << name <<endl;//error
cout << age << endl;
}

private:
int num;

};

class xstudent:public student
{

public:
void show2()
{
show1();//ok
cout << name << endl;//error
cout << age << endl;//?
cout << num << endl;//error
}
private:
int money;
};
int main()
{
xstudent xs;
xs.show2();
//s.show1();
/*
s.show();
s.name = "zhangfei";
s.age = 20;
*/

}

#include<iostream>
using namespace std;
class Parent
{
public:
Parent(string n,int a)
{
name = n;
age = a;
cout << "Parent() " << endl;
}
void show()
{
cout << name << endl;
cout << age << endl;
}
~Parent()
{
cout << "~Parent()" << endl;
}
private:
string name;
int age;

};

class Child:public Parent
{
public:
Child(string sn,int a,int n):Parent(sn,a)
{
num = n;
cout << "Child()" << endl;
}
void show()
{
Parent::show();
cout << num << endl;
}
~Child()
{
cout << "~Child()" << endl;
}
private:
int num;
};

int main()
{
Child c("guanyu",21,007);
c.show();
cout << "-----------------" << endl;
c.Parent::show();

}

#include<iostream>
using namespace std;
class Parent
{
public:
Parent(string n,int a)
{
name = n;
age = a;
cout << "Parent() " << endl;
}
virtual void show()
{
cout << name << endl;
cout << age << endl;
cout << "父类的show()" << endl;
}
~Parent()
{
cout << "~Parent()" << endl;
}
private:
string name;
int age;

};

class Child:public Parent
{
public:
Child(string sn,int a,int n):Parent(sn,a)
{
num = n;
cout << "Child()" << endl;
}
void show()
{
cout << "子类的show()" << endl;
cout << num << endl;
}
~Child()
{
cout << "~Child()" << endl;
}
private:
int num;
};

void func(Parent* p)
{
p->show();

}

int main()
{
Child c("guanyu",21,007);
Child c2("liubei",22,8);
c.show();
cout << "-----------------" << endl;

Parent *pp = &c;
pp->show();
pp = &c2;
pp->show();

cout << "---------------------" << endl;
func(&c);
func(&c2);
}