c++类和对象

void ChannelDown(){

pTelevision->ChannelDown();

}

//设置频道 遥控新增功能

void SetChannel(int channel){

if (channel < Television::minChannel || channel > Television::maxChannel){

return;

}

pTelevision->mChannel = channel;

}

//显示电视当前信息

void ShowTeleState(){

pTelevision->ShowTeleState();

}

private:

Television* pTelevision;

};

//直接操作电视

void test01(){

Television television;

television.ShowTeleState();

television.OnOrOff(); //开机

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.ChannelUp(); //频道+1

television.ChannelUp(); //频道+1

television.ShowTeleState();

}

//通过遥控操作电视

void test02(){

//创建电视

Television television;

//创建遥控

Remote remote(&television);

remote.OnOrOff();

remote.ChannelUp();//频道+1

remote.ChannelUp();//频道+1

remote.ChannelUp();//频道+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.ShowTeleState();

}

六、运算符重载


1.运算符重载基本概念

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.运算符重载碰上友元函数

在这里插入图片描述

class Person{

friend ostream& operator<<(ostream& os, Person& person);

public:

Person(int id,int age){

mID = id;

mAge = age;

}

private:

int mID;

int mAge;

};

ostream& operator<<(ostream& os, Person& person){

os << “ID:” << person.mID << " Age:" << person.mAge;

return os;

}

int main(){

Person person(1001, 30);

//cout << person; //cout.operator+(person)

cout << person << " | " << endl;

return EXIT_SUCCESS;

}

3.可重载的运算符

在这里插入图片描述

4.自增自减(++/–)运算符重载

在这里插入图片描述

class Complex{

friend ostream& operator<<(ostream& os,Complex& complex){

os << “A:” << complex.mA << " B:" << complex.mB << endl;

return os;

}

public:

Complex(){

mA = 0;

mB = 0;

}

//重载前置++

Complex& operator++(){

mA++;

mB++;

return *this;

}

//重载后置++

Complex operator++(int){

Complex temp;

temp.mA = this->mA;

temp.mB = this->mB;

mA++;

mB++;

return temp;

}

//前置–

Complex& operator–(){

mA–;

mB–;

return *this;

}

//后置–

Complex operator–(int){

Complex temp;

temp.mA = mA;

temp.mB = mB;

mA–;

mB–;

return temp;

}

void ShowComplex(){

cout << “A:” << mA << " B:" << mB << endl;

}

private:

int mA;

int mB;

};

void test(){

Complex complex;

complex++;

cout << complex;

++complex;

cout << complex;

Complex ret = complex++;

cout << ret;

cout << complex;

cout << “------” << endl;

ret–;

–ret;

cout << “ret:” << ret;

complex–;

–complex;

cout << “complex:” << complex;

}

在这里插入图片描述

5.指针运算符(*、->)重载

class Person{

public:

Person(int param){

this->mParam = param;

}

void PrintPerson(){

cout << “Param:” << mParam << endl;

}

private:

int mParam;

};

class SmartPointer{

public:

SmartPointer(Person* person){

this->pPerson = person;

}

//重载指针的->、*操作符

Person* operator->(){

return pPerson;

}

Person& operator*(){

return *pPerson;

}

~SmartPointer(){

if (pPerson != NULL){

delete pPerson;

}

}

public:

Person* pPerson;

};

void test01(){

//Person* person = new Person(100);

//如果忘记释放,那么就会造成内存泄漏

SmartPointer pointer(new Person(100));

pointer->PrintPerson();

}

6.赋值(=)运算符重载

在这里插入图片描述

class Person{

friend ostream& operator<<(ostream& os,const Person& person){

os << “ID:” << person.mID << " Age:" << person.mAge << endl;

return os;

}

public:

Person(int id,int age){

this->mID = id;

this->mAge = age;

}

//重载赋值运算符

Person& operator=(const Person& person){

this->mID = person.mID;

this->mAge = person.mAge;

return *this;

}

private:

int mID;

int mAge;

};

//1. =号混淆的地方

void test01(){

Person person1(10, 20);

Person person2 = person1; //调用拷贝构造

//如果一个对象还没有被创建,则必须初始化,也就是调用构造函数

//上述例子由于person2还没有初始化,所以会调用构造函数

//由于person2是从已有的person1来创建的,所以只有一个选择

//就是调用拷贝构造函数

person2 = person1; //调用operator=函数

//由于person2已经创建,不需要再调用构造函数,这时候调用的是重载的赋值运算符

}

//2. 赋值重载案例

void test02(){

Person person1(20, 20);

Person person2(30, 30);

cout << “person1:” << person1;

cout << “person2:” << person2;

person2 = person1;

cout << “person2:” << person2;

}

//常见错误,当准备给两个相同对象赋值时,应该首先检查一下这个对象是否对自身赋值了

//对于本例来讲,无论如何执行这些赋值运算都是无害的,但如果对类的实现进行修改,那么将会出现差异;

//3. 类中指针

class Person2{

friend ostream& operator<<(ostream& os, const Person2& person){

os << “Name:” << person.pName << " ID:" << person.mID << " Age:" << person.mAge << endl;

return os;

}

public:

Person2(char* name,int id, int age){

this->pName = new char[strlen(name) + 1];

strcpy(this->pName, name);

this->mID = id;

this->mAge = age;

}

#if 1

//重载赋值运算符

Person2& operator=(const Person2& person){

//注意:由于当前对象已经创建完毕,那么就有可能pName指向堆内存

//这个时候如果直接赋值,会导致内存没有及时释放

if (this->pName != NULL){

delete[] this->pName;

}

this->pName = new char[strlen(person.pName) + 1];

strcpy(this->pName,person.pName);

this->mID = person.mID;

this->mAge = person.mAge;

return *this;

}

#endif

//析构函数

~Person2(){

if (this->pName != NULL){

delete[] this->pName;

}

}

private:

char* pName;

int mID;

int mAge;

};

void test03(){

Person2 person1(“John”,20, 20);

Person2 person2(“Edward”,30, 30);

cout << “person1:” << person1;

cout << “person2:” << person2;

person2 = person1;

cout << “person2:” << person2;

}

在这里插入图片描述

7.等于和不等于(==、!=)运算符重载

class Complex{

public:

Complex(char* name,int id,int age){

this->pName = new char[strlen(name) + 1];

strcpy(this->pName, name);

this->mID = id;

this->mAge = age;

}

//重载==号操作符

bool operator==(const Complex& complex){

if (strcmp(this->pName,complex.pName) == 0 &&

this->mID == complex.mID &&

this->mAge == complex.mAge){

return true;

}

return false;

}

//重载!=操作符

bool operator!=(const Complex& complex){

if (strcmp(this->pName, complex.pName) != 0 ||

this->mID != complex.mID ||

this->mAge != complex.mAge){

return true;

}

return false;

}

~Complex(){

if (this->pName != NULL){

delete[] this->pName;

}

}

private:

char* pName;

int mID;

int mAge;

};

void test(){

Complex complex1(“aaa”, 10, 20);

Complex complex2(“bbb”, 10, 20);

if (complex1 == complex2){ cout << “相等!” << endl; }

if (complex1 != complex2){ cout << “不相等!” << endl; }

}

8.函数调用符号()重载

class Complex{

public:

int Add(int x,int y){

return x + y;

}

int operator()(int x,int y){

return x + y;

}

};

void test01(){

Complex complex;

cout << complex.Add(10,20) << endl;

//对象当做函数来调用

cout << complex(10, 20) << endl;

}

9.不要重载&&、||

在这里插入图片描述

class Complex{

public:

Complex(int flag){

this->flag = flag;

}

Complex& operator+=(Complex& complex){

this->flag = this->flag + complex.flag;

return *this;

}

bool operator&&(Complex& complex){

return this->flag && complex.flag;

}

public:

int flag;

};

int main(){

Complex complex1(0); //flag 0

Complex complex2(1); //flag 1

//原来情况,应该从左往右运算,左边为假,则退出运算,结果为假

//这边却是,先运算(complex1+complex2),导致,complex1的flag变为complex1+complex2的值, complex1.a = 1

// 1 && 1

//complex1.operator&&(complex1.operator+=(complex2))

if (complex1 && (complex1 += complex2)){

cout << “真!” << endl;

}

else{

cout << “假!” << endl;

}

return EXIT_SUCCESS;

}

在这里插入图片描述

10.符号重载总结

在这里插入图片描述

11.附录:运算符和结合性

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

七、继承和派生


1.继承概述

为什么需要继承

在这里插入图片描述

网页类

class IndexPage{

public:

//网页头部

void Header(){

cout << “网页头部!” << endl;

}

//网页左侧菜单

void LeftNavigation(){

cout << “左侧导航菜单!” << endl;

}

//网页主体部分

void MainBody(){

cout << “首页网页主题内容!” << endl;

}

//网页底部

void Footer(){

cout << “网页底部!” << endl;

}

private:

string mTitle; //网页标题

};

#if 0

//如果不使用继承,那么定义新闻页类,需要重新写一遍已经有的代码

class NewsPage{

public:

//网页头部

void Header(){

cout << “网页头部!” << endl;

}

//网页左侧菜单

void LeftNavigation(){

cout << “左侧导航菜单!” << endl;

}

//网页主体部分

void MainBody(){

cout << “新闻网页主体内容!” << endl;

}

//网页底部

void Footer(){

cout << “网页底部!” << endl;

}

private:

string mTitle; //网页标题

};

void test(){

NewsPage* newspage = new NewsPage;

newspage->Header();

newspage->MainBody();

newspage->LeftNavigation();

newspage->Footer();

}

#else

//使用继承,可以复用已有的代码,新闻业除了主体部分不一样,其他都是一样的

class NewsPage : public IndexPage{

public:

//网页主体部分

void MainBody(){

cout << “新闻网页主主体内容!” << endl;

}

};

void test(){

NewsPage* newspage = new NewsPage;

newspage->Header();

newspage->MainBody();

newspage->LeftNavigation();

newspage->Footer();

}

#endif

int main(){

test();

return EXIT_SUCCESS;

}

继承基本概念

在这里插入图片描述

在这里插入图片描述

派生类定义

在这里插入图片描述

2.派生类访问控制

在这里插入图片描述

在这里插入图片描述

//基类

class A{

public:

int mA;

protected:

int mB;

private:

int mC;

};

//1. 公有(public)继承

class B : public A{

public:

void PrintB(){

cout << mA << endl; //可访问基类public属性

cout << mB << endl; //可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

class SubB : public B{

void PrintSubB(){

cout << mA << endl; //可访问基类public属性

cout << mB << endl; //可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

void test01(){

B b;

cout << b.mA << endl; //可访问基类public属性

//cout << b.mB << endl; //不可访问基类protected属性

//cout << b.mC << endl; //不可访问基类private属性

}

//2. 私有(private)继承

class C : private A{

public:

void PrintC(){

cout << mA << endl; //可访问基类public属性

cout << mB << endl; //可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

class SubC : public C{

void PrintSubC(){

//cout << mA << endl; //不可访问基类public属性

//cout << mB << endl; //不可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

void test02(){

C c;

//cout << c.mA << endl; //不可访问基类public属性

//cout << c.mB << endl; //不可访问基类protected属性

//cout << c.mC << endl; //不可访问基类private属性

}

//3. 保护(protected)继承

class D : protected A{

public:

void PrintD(){

cout << mA << endl; //可访问基类public属性

cout << mB << endl; //可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

class SubD : public D{

void PrintD(){

cout << mA << endl; //可访问基类public属性

cout << mB << endl; //可访问基类protected属性

//cout << mC << endl; //不可访问基类private属性

}

};

void test03(){

D d;

//cout << d.mA << endl; //不可访问基类public属性

//cout << d.mB << endl; //不可访问基类protected属性

//cout << d.mC << endl; //不可访问基类private属性

}

3.继承中的构造和析构

继承中的对象模型

在这里插入图片描述

对象构造和析构的调用原则

在这里插入图片描述

class A{

public:

A(){

cout << “A类构造函数!” << endl;

}

~A(){

cout << “A类析构函数!” << endl;

}

};

class B : public A{

public:

B(){

cout << “B类构造函数!” << endl;

}

~B(){

cout << “B类析构函数!” << endl;

}

};

class C : public B{

public:

C(){

cout << “C类构造函数!” << endl;

}

~C(){

cout << “C类析构函数!” << endl;

}

};

void test(){

C c;

}

在这里插入图片描述

class D{

public:

D(){

cout << “D类构造函数!” << endl;

}

~D(){

cout << “D类析构函数!” << endl;

}

};

class A{

public:

A(){

cout << “A类构造函数!” << endl;

}

~A(){

cout << “A类析构函数!” << endl;

}

};

class B : public A{

public:

B(){

cout << “B类构造函数!” << endl;

}

~B(){

cout << “B类析构函数!” << endl;

}

};

class C : public B{

public:

C(){

cout << “C类构造函数!” << endl;

}

~C(){

cout << “C类析构函数!” << endl;

}

public:

D c;

};

void test(){

C c;

}

4.继承中同名成员的处理方法

在这里插入图片描述

class Base{

public:

Base():mParam(0){}

void Print(){ cout << mParam << endl; }

public:

int mParam;

};

class Derived : public Base{

public:

Derived():mParam(10){}

void Print(){

//在派生类中使用和基类的同名成员,显示使用类名限定符

cout << Base::mParam << endl;

cout << mParam << endl;

}

//返回基类重名成员

int& getBaseParam(){ return Base::mParam; }

public:

int mParam;

};

int main(){

Derived derived;

//派生类和基类成员属性重名,子类访问成员默认是子类成员

cout << derived.mParam << endl; //10

derived.Print();

//类外如何获得基类重名成员属性

derived.getBaseParam() = 100;

cout << “Base:mParam:” << derived.getBaseParam() << endl;

return EXIT_SUCCESS;

}

注意: 如果重新定义了基类中的重载函数,将会发生什么?

class Base{

public:

void func1(){

cout << “Base::void func1()” << endl;

};

void func1(int param){

cout << “Base::void func1(int param)” << endl;

}

void myfunc(){

cout << “Base::void myfunc()” << endl;

}

};

class Derived1 : public Base{

public:

void myfunc(){

cout << “Derived1::void myfunc()” << endl;

}

};

class Derived2 : public Base{

public:

//改变成员函数的参数列表

void func1(int param1, int param2){

cout << “Derived2::void func1(int param1,int param2)” << endl;

};

};

class Derived3 : public Base{

public:

//改变成员函数的返回值

int func1(int param){

cout << “Derived3::int func1(int param)” << endl;

return 0;

}

};

int main(){

Derived1 derived1;

derived1.func1();

derived1.func1(20);

derived1.myfunc();

cout << “-------------” << endl;

Derived2 derived2;

//derived2.func1(); //func1被隐藏

//derived2.func1(20); //func2被隐藏

derived2.func1(10,20); //重载func1之后,基类的函数被隐藏

derived2.myfunc();

cout << “-------------” << endl;

Derived3 derived3;

//derived3.func1(); 没有重新定义的重载版本被隐藏

derived3.func1(20);

derived3.myfunc();

return EXIT_SUCCESS;

}

在这里插入图片描述

5.非自动继承的函数

在这里插入图片描述

6.继承中的静态成员特性

在这里插入图片描述

在这里插入图片描述

7.多继承

多继承概念

在这里插入图片描述

在这里插入图片描述

菱形继承和虚继承

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

虚继承实现原理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

八、多态


1.多态基本概念

在这里插入图片描述

//计算器

class Caculator{

public:

void setA(int a){

this->mA = a;

}

void setB(int b){

this->mB = b;

}

void setOperator(string oper){

this->mOperator = oper;

}

int getResult(){

if (this->mOperator == “+”){

return mA + mB;

}

else if (this->mOperator == “-”){

return mA - mB;

}

else if (this->mOperator == “*”){

return mA * mB;

}

else if (this->mOperator == “/”){

return mA / mB;

}

}

private:

int mA;

int mB;

string mOperator;

};

//这种程序不利于扩展,维护困难,如果修改功能或者扩展功能需要在源代码基础上修改

//面向对象程序设计一个基本原则:开闭原则(对修改关闭,对扩展开放)

//抽象基类

class AbstractCaculator{

public:

void setA(int a){

this->mA = a;

}

virtual void setB(int b){

this->mB = b;

}

virtual int getResult() = 0;

protected:

int mA;

int mB;

string mOperator;

};

//加法计算器

class PlusCaculator : public AbstractCaculator{

public:

virtual int getResult(){

return mA + mB;

}

};

//减法计算器

class MinusCaculator : public AbstractCaculator{

public:

virtual int getResult(){

return mA - mB;

}

};

//乘法计算器

class MultipliesCaculator : public AbstractCaculator{

public:

virtual int getResult(){

return mA * mB;

}

};

void DoBussiness(AbstractCaculator* caculator){

int a = 10;

int b = 20;

caculator->setA(a);

caculator->setB(b);

cout << “计算结果:” << caculator->getResult() << endl;

delete caculator;

}

2.向上类型转换及问题

问题抛出

在这里插入图片描述

在这里插入图片描述

问题解决思路

在这里插入图片描述

问题解决方案(虚函数,vitual function)

在这里插入图片描述

在这里插入图片描述

3.C++如何实现动态绑定

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.抽象基类和纯虚函数(pure virtual function)

在这里插入图片描述

在这里插入图片描述

//抽象制作饮品

class AbstractDrinking{

public:

//烧水

virtual void Boil() = 0;

//冲泡

virtual void Brew() = 0;

//倒入杯中

virtual void PourInCup() = 0;

//加入辅料

virtual void PutSomething() = 0;

//规定流程

void MakeDrink(){

Boil();

Brew();

PourInCup();

PutSomething();

}

};

//制作咖啡

class Coffee : public AbstractDrinking{

public:

//烧水

virtual void Boil(){

cout << “煮农夫山泉!” << endl;

}

//冲泡

virtual void Brew(){

cout << “冲泡咖啡!” << endl;

}

//倒入杯中

virtual void PourInCup(){

cout << “将咖啡倒入杯中!” << endl;

}

//加入辅料

virtual void PutSomething(){

cout << “加入牛奶!” << endl;

}

};

//制作茶水

class Tea : public AbstractDrinking{

public:

//烧水

virtual void Boil(){

cout << “煮自来水!” << endl;

}

//冲泡

virtual void Brew(){

cout << “冲泡茶叶!” << endl;

}

//倒入杯中

virtual void PourInCup(){

cout << “将茶水倒入杯中!” << endl;

}

//加入辅料

virtual void PutSomething(){

cout << “加入食盐!” << endl;

}

};

//业务函数

void DoBussiness(AbstractDrinking* drink){

drink->MakeDrink();

delete drink;

}

void test(){

DoBussiness(new Coffee);

cout << “--------------” << endl;

DoBussiness(new Tea);

}

5.纯虚函数和多继承

在这里插入图片描述

6.虚析构函数

虚析构函数作用

虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

class People{

public:

People(){

cout << “构造函数 People!” << endl;

}

virtual void showName() = 0;

virtual ~People(){

cout << “析构函数 People!” << endl;

}

};

class Worker : public People{

public:

Worker(){

cout << “构造函数 Worker!” << endl;

pName = new char[10];

}

virtual void showName(){

cout << “打印子类的名字!” << endl;

}

~Worker(){

cout << “析构函数 Worker!” << endl;

if (pName != NULL){

delete pName;

}

}

private:

char* pName;

};

void test(){

People* people = new Worker;

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值