C++面向对象三大特征

封装

封装是将现实生活中的事物定义为类,将事物的数据抽象为属性,将事物的行为抽象为方法。

封装的关键字是class。

继承

子类继承父类的属性和方法,使得子类具备父类的特征。这样可以实现代码重用。

定义类时可以从现有类继承,被继承的类叫父类或超类、基类;新定义的类叫子类或派生类。子类中不需要定义父类中已有的属性和方法,只需要定义父类没有而子类新增的成员。

类的继承类型

单继承,子类只有一个基类。

多继承,子类有多于一个基类。

直接继承,教师类是人类的直接继承;人类是教师类的直接基类。

间接继承,教师管理人员类是人类的间接继承;人类是教师管理人员类的间接基类。

方法的隐藏(重定义)

子类中定义和父类方法名完全相同的方法时,子类的函数屏蔽与其同名的父类函数,这叫方法的隐藏。

#include <iostream>
#include "Pet.h"
#include "Cat.h"
#include "Dog.h"

using namespace std;

int main()
{
	Pet pet("皮卡", 3);
	pet.barking();
	pet.running();
	pet.barking(3);

	Cat cat("叮当", 5);
	cat.barking();
	cat.running();
	cat.barking(3);


	Dog dog("旺财", 8);
	dog.barking();
	dog.running();
	dog.guardHouse();
	/*
		因为Dog 定义了barking(),其父类Pet中的barking()和barking(int n)
		都被隐藏了,所以Dog的对象不能使用barking(int n)方法。		
	*/
	//	dog.barking(3); 

	return 0;
}

类的继承方式

//Pet.h

#pragma once

class Pet
{
	//protected修饰的数据成员和成员函数,允许本类和本类的派生类(子类)的成员函数访问,对类外部不可见。
protected:
	char m_name[20];
	int m_age;

public:
	Pet(const char* name, int age);
	void running();
	void barking();
	void barking(int n);
};

//Pet.c

#include "Pet.h"
#include <iostream>
/*#include <iomanip>  strcpy_s等字符串处理函数包含在这个库内。不导入iostream时可以导入iomanip。*/
using namespace std;
Pet::Pet(const char* name, int age)
{
	strcpy_s(m_name, 20, name);
	m_age = age;
}

void Pet::running()
{
	cout << m_name << "在跑" << endl;
}

void Pet::barking()
{
	cout << m_name << "在叫" << endl;
}

void Pet::barking(int n)
{
	cout << m_name << "叫了" << n << "声" << endl;
}

//Bird.h

#pragma once
#include "Pet.h"
/*
	private继承方式
	Bird private方式继承Pet,
	Bird可以访问Pet的public或protected属性和方法,
	但是其子类不能访问Pet的任何属性和方法。	
*/
class Bird : private Pet
{
public:
	Bird(const char* name, int age);
	void action();	
};

//Bird.c

#include "Bird.h"

Bird::Bird(const char* name, int age) : Pet(name, age)
{
}
/*
	由于Fish private继承自 Pet, Pet的方法不能被外部访问,
	但是能够被Fish的方法访问。
*/
void Bird::action()
{
	running();
	barking();
}

//Pigeon.h

#pragma once
#include "Bird.h"

class Pigeon : public Bird
{
public:
	Pigeon(const char* name, int age);
	void fly();
};

//Pigeon.c

#include "Pigeon.h"
#include <iostream>
using namespace std;

Pigeon::Pigeon(const char* name, int age) : Bird(name, age)
{
}

void Pigeon::fly()
{
	/*
		由于Pigeon的父类Bird采用private方式继承Pet,
		Brid继承到的barking()等方法,访问权限从public变成了private
		Brid继承到的m_name等属性,访问权限从protected变成了private,
		Pigeon类中既不能访问Pet的方法,也不能访问Pet的属性。
		barking();
		cout << m_name << "在游泳" << endl;
	*/
	
}

//Cat.h

#pragma once
#include "Pet.h"

/*
	声明Cat类继承自Pet类;
	Cat类是Pet类的子类或派生类;
	Pet类是Cat类的父类、基类或超类。
*/	
class Cat : public Pet
{
public:
	//	派生类不继承父类的构造函数,需要至少实现1个父类类构造函数。
	Cat(const char* name, int age);
};

//Cat.c

#include "Cat.h"

/*
	子类构造函数必须先执行父类构造函数,
	子类的构造函数的构造列表中包含一个父类构造函数。
*/
Cat::Cat(const char* name, int age) : Pet(name, age)
{

}

//Dog.h

#pragma once
#include "Pet.h"

class Dog : public Pet
{	
public:
	Dog(const char* name, int age);
	void guardHouse();
	void barking();
};

//Dog.c

#include <iostream>
#include "Dog.h"

using namespace std;

Dog::Dog(const char* name, int age) : Pet(name, age)
{	
}

void Dog::guardHouse()
{
	cout << m_name << "在看门" << endl;
}

void Dog::barking()
{
	cout << m_name << "汪汪叫" << endl;
}

//Fish.h

#pragma once
#include "Pet.h"

/*
	protected继承方式
	Fish protected方式继承Pet,
	Fish及其子类可以访问Pet的public或protected属性和方法。	
*/	
class Fish : protected Pet
{
public:
	Fish(const char* name, int age);
	void action();
};

//Fish.c

#include "Fish.h"

Fish::Fish(const char* name, int age) : Pet(name, age)
{
}
/*
	由于Fish protected继承自 Pet, Pet的方法不能被外部访问,
	但是能够被Fish的方法访问。
*/
void Fish::action()
{
	running();	
	barking();
}

//Whale.h

#pragma once
#include "Fish.h"


class Whale : public Fish
{
public:
	Whale(const char* name, int age);
	void swimming();
};

//Whale.c

#include "Whale.h"
#include <iostream>
using namespace std;

Whale::Whale(const char* name, int age) : Fish(name, age)
{
}

void Whale::swimming()
{
	barking();
	cout << m_name << "在游泳" << endl;
}

//类的继承方式

#include <iostream>
#include "Pet.h"
#include "Fish.h"
#include "Bird.h"
#include "Whale.h"

using namespace std;

int main()
{
	Pet pet("皮卡", 3);
	pet.barking();
	pet.running();
	pet.barking(3);

	Fish fish("食人鱼", 3);
	/*
		由于Fish protected继承自 Pet, Pet的方法不能被外部访问
		fish.barking();
		fish.running();
		fish.barking(3);
	*/
	fish.action();

	Bird bird("食人鸟", 3);
	/*
		由于Brid protected继承自 Pet, Pet的方法不能被外部访问
		bird.barking();
		bird.running();
		bird.barking(3);
	*/
	bird.action();

	Whale whale("杀人鲸", 2);
	whale.action();
	whale.swimming();

	return 0;
}

派生类的构造和析构过程

派生类的构造函数执行顺序

调用基类构造函数

调用派生类构造函数

派生类的析构函数执行顺序

执行派生类析构函数

执行基类析构函数

#include <iostream>

using namespace std;

class Animal
{
protected:
	char m_type[20];
public:
	Animal(const char* type)
	{
		cout << type << "Animal 构造中" << endl;
		strcpy_s(m_type, 20, type);
	}	
	void show()
	{
		cout << "Animal: " << m_type << endl;
	}
	~Animal()
	{
		cout << "Animal析构中" << endl;
	}
};

class Tiger : public Animal
{
private:
	int m_weight;
public:
	Tiger(const char* type, int weight) : Animal(type)
	{
		cout << type << "Tiger 构造中" << endl;
		m_weight = weight;
	}
	void show()
	{
		cout << "Tiger: " << m_type << ", "<< m_weight << endl;
	}
	~Tiger()
	{
		cout << "Tiger析构中" << endl;
	}
};

int main()
{
	Animal animal("大鹅");
	animal.show();
	Tiger tiger("大虎", 200000);
	tiger.show();
	//	父类指针可以指向子类对象
	Animal* p = &animal;
	p->show();
	p = &tiger;
	p->show();
	return 0;
}

多继承简介

一个派生类可以有多于一个基类,称之为多继承。

多继承派生类的构造顺序是按照基类声明顺序构造基类,所有基类构造函数执行完毕后,执行派生类构造函数。析构顺和构造顺序相反。

多继承派生类的每个基类都应该指定继承类型。

当多个基类存在同名成员时, 使用 基类名::成员名 访问基类对应的成员。

#include <iostream>

using namespace std;

//	定义基类A
class BaseA
{
protected:
	int m_a;
	int m_c = 0;
public:
	BaseA(int a)
	{
		cout << "BaseA构造中" << endl;
		m_a = a;
	}

	~BaseA()
	{
		cout << "BaseA析构中" << endl;
	}
};

//	定义基类B
class BaseB
{
protected:
	int m_b;
	int m_c = 10;
public:
	BaseB(int b)
	{
		cout << "BaseB构造中" << endl;
		m_b = b;
	}

	~BaseB()
	{
		cout << "BaseB析构中" << endl;
	}
};

//	定义派生类Derived,共有继承自BaseA和BaseB。
class Derived : public BaseB, public BaseA	//	多继承按照声明顺序依次调用基类构造函数
{
public:
	Derived(int a, int b) : BaseA(a), BaseB(b)
	{
		cout << "Derived构造中" << endl;
	}
	~Derived()
	{
		cout << "Derived析构中" << endl;
	}
	void show()
	{
		cout << "m_a: " << m_a << " m_b: " << m_b << endl;
		//	当多个基类存在同名成员时, 使用 基类名::成员名 访问基类对应的成员。
		cout << "BaseA::m_c: " << BaseA::m_c << " BaseB::m_c" << BaseB::m_c << endl;
	}
};

int main()
{
	Derived derived(1, 2);
	derived.show();

	return 0;
}

多态

多态的一般含义是一个名字有多种具体的解释。C++语言中的多态性分为编译时的静态多态和运行时的动态多态。前者通过函数重载和运算符重载来实现,后者通过继承于虚函数实现。

静态多态

静态多态通过函数重载或运算符重载实现,其多态性在编译时已经决定了。

#include <iostream>

using namespace std;
//	Cat中有函数重载,产生了静态多态。
class Cat
{
private:
	char m_name[20];
	int m_full = 100;
public:
	Cat(const char* name)
	{
		strcpy_s(m_name, 20, name);
	}

	void play()
	{
		m_full--;
	}

	void play(int n)
	{
		m_full -= n;
	}

	void eat()
	{		
		if (m_full >= 100)
		{			
			cout << m_name << "我吃不下了" << endl;
			return;
		}
		m_full++;
	}
	void eat(int n)
	{
		for(int i = 0; i < n; i++)
		{
			if (m_full >= 100)
			{
				cout << m_name << "我吃不下了" << endl;
				break;
			}
			eat();
		} 
	}
	void show()
	{
		cout << m_name << " m_full: " << m_full << endl;
	}
};

int main()
{
	Cat cat("Tom");
	cat.show();
	cat.play();
	cat.play(10);
	cat.show();
	cat.eat(15);
	cat.show();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值