C++冲鸭~【面向对象】

C++类和对象

类定义

使用关键字 class 定义 Box 数据类型,包含了三个成员变量 length、breadth 和 height:

class box{
	public:
		double length;		// 盒子长
		double breadth;		// 盒子宽
		double height;		// 盒子高
};

对象定义

Box box1;
Box box2;

访问数据成员

示例:

#include 
using namespace std;

class Box{
	public:
		double length;
		double breadth;
		double height;

		// 成员函数声明
		double get(void);
		void set( double len, double bre, double hei );
};

// 成员函数定义
double Box::get(void){
	return length * breadth * height;
}

void Box::set( double len, double bre, double lei ){
	length = len;
	breadth = bre;
	height = hei;
}

int main() {
	Box box1;
	Box box2;
	Box box3;
	double volumn = 0.0;	// 用于存储体积

	box1.length = 5.0;
	box1.breadth = 6.0;
	box1.height = 7.0;

	box2.height = 10.0;
    box2.length = 12.0;
    box2.breadth = 13.0;

	volume = box1.height * box1.length * box1.breadth;
    cout << "box1 的体积:" << volume <<endl;

	volume = box2.height * box2.length * box2.breadth;
    cout << "box2 的体积:" << volume <<endl;

	box3.set(16.0, 8.0, 12.0);
	volumn = box3.get();
	cout << "box3 的体积:" << volumn <<endl;

	return 0;
}

类成员函数

#include 
using namespace std;
 
class Box
{
   public:
      double length;         // 长度
      double breadth;        // 宽度
      double height;         // 高度
 
      // 成员函数声明
      double getVolume(void);
      void setLength( double len );
      void setBreadth( double bre );
      void setHeight( double hei );
};
 
// 成员函数定义
double Box::getVolume(void){
    return length * breadth * height;
}
 
void Box::setLength( double len ){
    length = len;
}
 
void Box::setBreadth( double bre ){
    breadth = bre;
}
 
void Box::setHeight( double hei ){
    height = hei;
}
 
int main(){
   Box box1;                // 声明 Box1,类型为 Box
   Box box2;                // 声明 Box2,类型为 Box
   double volume = 0.0;     // 用于存储体积
   
   box1.setLength(6.0); 
   box1.setBreadth(7.0); 
   box1.setHeight(5.0);
 
   box2.setLength(12.0); 
   box2.setBreadth(13.0); 
   box2.setHeight(10.0);
 
   volume = box1.getVolume();
   cout << "box1 的体积:" << volume <<endl;
 
   volume = box2.getVolume();
   cout << "box2 的体积:" << volume <<endl;
   
   return 0;
}

C++类访问修饰符【公有、私有、受保护】

public

#include 
using namespace std;

class Line{
	public:
		double length;
		void setLength( double len );
		double getLength( void );
};

double Line::getLength(void){
	return length;
}

void Line::setLength( double len ){
	length = len;
}

int main(){
	Line line;
	
	line.setLength(6.0);
	cout << "Length of line:" << line.getLength() <<endl;

	line.length = 10.0;
	cout << "Length of line:" << line.length <<endl;
	
	return 0;
}

private

【默认情况下,类的所有成员都是私有的,私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的,只有类和友元函数可以访问私有成员】

class Box{
	double width;	// 默认私有
	public:
		double length;
		void setWidth( double wid );
		double getWidth( void );
};
#include 
using namespace std;

class Box{
	public:
		double length;
		void setWidth( double wid );
		double getWidth(void);
	private:
		double width;
};

void Box::setWidth( double wid ){
	width = wid;
}

double Box::getWidth(void){
	return width;
}

int main(){
	Box box;

	// 不使用成员函数设置长度
   box.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成员函数设置宽度
   // box.width = 10.0; // Error: 因为 width 是私有的
   box.setWidth(10.0);  // 使用成员函数设置宽度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

protected

protected(受保护的)成员变量或函数与私有成员十分相似,但有一点不同,protected成员在派生类(子类)中是可访问的。

#include 
using namespace std;

class Box{
	protected:
		double width;
};

class SmallBox:Box{
	public:
		void setSmallWidth( double wid );
		double getSmallWidth(void);
};

double SmallBox::getSmallWidth(void){
	return width;
}

void SmallBox::setSmallWidth( double wid ){
	width = wid;
}

int main(){
	SmallBox box;
	
	box.setSmallWidth(5.0);
	cout << "Width of box :" << box.getSmallWidth() <<endl;

	return 0;
}

继承中的特点:
有public,protected,private三种继承方式,他们对应地改变了基类成员的访问属性。

  • public继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:public,protected,private。
  • protected继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:protected,protected,private。
  • private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private,private,private。
    但无论哪种继承方式,以下两点不变:
  • private成员只能被奔雷成员(类内)和友元访问,不能被派生类访问;
  • protected成员可以被派生类访问。
public继承
#include
#include
using namespace std;
 
class A{
public:
  int a;
  A(){
    a1 = 1;
    a2 = 2;
    a3 = 3;
    a = 4;
  }
  void fun(){
    cout << a << endl;    //正确
    cout << a1 << endl;   //正确
    cout << a2 << endl;   //正确
    cout << a3 << endl;   //正确
  }
public:
  int a1;
protected:
  int a2;
private:
  int a3;
};
class B : public A{
public:
  int a;
  B(int i){
    A();
    a = i;
  }
  void fun(){
    cout << a << endl;       //正确,public成员
    cout << a1 << endl;       //正确,基类的public成员,在派生类中仍是public成员。
    cout << a2 << endl;       //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。
  }
};
int main(){
  B b(10);
  cout << b.a << endl;
  cout << b.a1 << endl;   //正确
  cout << b.a2 << endl;   //错误,类外不能访问protected成员
  cout << b.a3 << endl;   //错误,类外不能访问private成员
  system("pause");
  return 0;
}
protected继承
#include
#include
using namespace std;
class A{
public:
  int a;
  A(){
    a1 = 1;
    a2 = 2;
    a3 = 3;
    a = 4;
  }
  void fun(){
    cout << a << endl;    //正确
    cout << a1 << endl;   //正确
    cout << a2 << endl;   //正确
    cout << a3 << endl;   //正确
  }
public:
  int a1;
protected:
  int a2;
private:
  int a3;
};
class B : protected A{
public:
  int a;
  B(int i){
    A();
    a = i;
  }
  void fun(){
    cout << a << endl;       //正确,public成员。
    cout << a1 << endl;       //正确,基类的public成员,在派生类中变成了protected,可以被派生类访问。
    cout << a2 << endl;       //正确,基类的protected成员,在派生类中还是protected,可以被派生类访问。
    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。
  }
};
int main(){
  B b(10);
  cout << b.a << endl;       //正确。public成员
  cout << b.a1 << endl;      //错误,protected成员不能在类外访问。
  cout << b.a2 << endl;      //错误,protected成员不能在类外访问。
  cout << b.a3 << endl;      //错误,private成员不能在类外访问。
  system("pause");
  return 0;
}
private 继承
#include
#include
using namespace std;
class A{
public:
  int a;
  A(){
    a1 = 1;
    a2 = 2;
    a3 = 3;
    a = 4;
  }
  void fun(){
    cout << a << endl;    //正确
    cout << a1 << endl;   //正确
    cout << a2 << endl;   //正确
    cout << a3 << endl;   //正确
  }
public:
  int a1;
protected:
  int a2;
private:
  int a3;
};
class B : private A{
public:
  int a;
  B(int i){
    A();
    a = i;
  }
  void fun(){
    cout << a << endl;       //正确,public成员。
    cout << a1 << endl;       //正确,基类public成员,在派生类中变成了private,可以被派生类访问。
    cout << a2 << endl;       //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。
    cout << a3 << endl;       //错误,基类的private成员不能被派生类访问。
  }
};
int main(){
  B b(10);
  cout << b.a << endl;       //正确。public成员
  cout << b.a1 << endl;      //错误,private成员不能在类外访问。
  cout << b.a2 << endl;      //错误, private成员不能在类外访问。
  cout << b.a3 << endl;      //错误,private成员不能在类外访问。
  system("pause");
  return 0;
}

C++类构造函数&析构函数

类的析构函数

类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

#include 
using namespace std;

class Line{
	public:
		void setLength( double len );
		double getLength(void);
		Line(); // 这是构造函数

	privatedouble length;
};

// 成员函数定义,包括构造函数
Line::Line(void){
	cout << "Object is being creaded" <<endl;
}

void Line::setLength( double len ){
	length = len;
}

double getLength(void){
	return length;
}

int main(){
	Line line;
	
	line.setLength(6.0);
	cout << "Length of line:" << line.getLength() <<endl;

	return 0;
}

编译执行结果:

Object is being created
Length of line : 6

带参数的构造函数

默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数,这样在创建对象时就会给对象赋初始值。

#include 
using namespace std;

class Line{
	public:
		void setLength( double len );
		double getLength(void);
		Line(double len);	// 带参数的构造函数
	
	private:
		double length;
};

Line::Line( double len ){
	cout << "Object is being created, length = " << len <<endl;
	length = len;
}

void Line::setLength( double len ){
	length = len;
}

void setLength( double len ){
	length = len;
}

double getLength(void){
	return length;
}

int main(){
	Line line(10.0);
	
	cout << "Length of line:" << line.getLength() <<endl;
	line.setLength(6.0);
	cout << "Length of line:" << line.getLength() <<endl;
	
	return 0;
}

编译和执行结果:

Object is being created, length = 10
Length of line : 10
Length of line : 6

使用初始化列表来初始化字段

Line::Line( double len ): length(len){
	cout << "Object is being created, length = " << len <<endl;
}

等价于

Line::Line( double len ){
	length = len;
	cout << "Object is being created, length = " << len <<endl;
}

假设有一个类C,具有多个字段XYZ等需要进行初始化,同理地,可以使用上面语法,只需要在不同的字段使用逗号进行分隔:

C::C( double a, double b, double c ): X(a), Y(b), Z(c){
	...
}

类的析构函数

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,他不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序前释放资源。

#include 
using namespace std;

class Line{
	public:
		void setLength( double len );
		double getLength(void);
		Line();		// 构造函数
		~Line();	// 析构函数

	privatedouble length;
};

Line::Line(void){
	cout << "Object is being created" <<endl;
}
Line::~Line(void){
	cout << "Object is being deleted" <<endl;
}

void Line::setLength( double len ){
	length = len;
}

double Line::getLength(void){
	return length;
}

int main(){
	Line line;
	line.setLength(6.0);
	cout << "Length of line:" << line.getLength() <<endl;

	return 0;
}

编译和执行结果:

Object is being created
Length of line : 6
Object is being deleted

C++拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它是创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。
拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象;
  • 复制对象把它作为参数传递给函数;
  • 复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并从动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) {
	// 构造函数的主体
}
//obj是一个对象引用,该对象是用于初始化另一个对象的。

实例:

#include 
using namespace std;

class Line{
	public:
		int getLength(void);
		Line( int len );	// 构造函数
		Line( const Line &obj );	// 拷贝构造函数
		~Line();	// 析构函数
	private:
		int *ptr;
};

Line::Line(int len){
	cout << "调用构造函数" <<endl;
	// 为指针分配内存
	ptr = new int;
	*ptr = len;
}

Line::Line(const Line &obj){
	cout << "调用拷贝构造函数并为指针ptr分配内存" <<endl;
	ptr = new int;
	*ptr = *obj.ptr;	// 拷贝值
}

Line::~Line(void){
	cout << "释放内存" <<endl;
	delete ptr;
}

int Line::getLength(void){
	return length;
}

void display(line obj){
	cout << "line 大小:" << obj.getLength() <<endl;
}

int main(){
	Line line(10);
	display(line);
	
	return 0;
}

编译和执行结果:

调用构造函数
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
释放内存

通过使用已有的同类型的对象来初始化新创建的对象

#include 
using namespace std;

class Line{
	public:
		int getLength( void );
		Line( int len );
		Line( const Line &obj );
		~Line();
	private:
		int *ptr;
};

Line::Line(int len){
	cout << "调用构造函数" <<endl;
	ptr = new int;
	*ptr = len;
}

Line::Line(const Line &obj){
	cout << "调用拷贝构造函数并为指针ptr分配内存" <<endl;
	ptr = new int;
	*ptr = *obj.ptr;	// 拷贝值
}

Line::~Line(void){
	cout << "释放内存" <<endl;
	delete ptr;
}

int Line::getLength(void){
	return *ptr;
}

void display(Line obj){
	cout << "line 大小:" << obj.getLength() <<endl;
}

int main(){
	Line line1(10);
	
	Line line2 = line1;		// 这里也调用了拷贝构造函数

	display(line1);
	display(line2);
	
	return 0;
}

编译执行结果:

调用构造函数
调用拷贝构造函数并为指针 ptr 分配内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
释放内存
释放内存

C++友元函数

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型在类的定义中出现,但是友元函数不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字friend:

class Box{
		double width;
	public:
		double length;
		friend void printWidth( Box box );
		void setWidth( double wid );
};

声明类ClassTwo的所有成员函数作为类ClassOne的友元,需要在类ClassOne的定义中前置如下声明:
friend class ClassTwo;

#include 
using namespace std;

class Box{
		double width;
	public:
		friend void printWidth( Box box );
		void setWidth( double wid );
};

void Box::setWidth( double wid ){
	width = wid;
}

void printWidth(Box box){
	/*因为printWidth()是Box的友元,它可以直接访问该类的任何成员*/
	cout << "width of box:" << box.width <<endl;
}

int main(){
	Box box;

	box.setWidth(10.0);
	printWidth(box);

	return 0;
}

编译执行结果:

Width of box : 10

C++内联函数【通过内联函数,编译器试图在调用函数的地方扩展函数体中的代码】

#include 
using namespace std;

inline int Max(int x, int y){
	return (x > y)? x : y;
}

int main(){
	cout << "Max (20, 10):" << Max(20, 10) <<endl;
	cout << "Max (0, 200):" << Max(0, 200) <<endl;
	cout << "Max (100, 1010):" << Max(100, 1010) <<endl;
	return 0;
}

**内联函数inline:**引入内联函数的目的是为了解决程序中函数调用的效率问题,这么说吧,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。这其实就是个空间代价换时间的节省。所以内联函数一般都是1-5行的小函数。在使用内联函数时要留神:

  1. 在内联函数内不允许使用循环语句开关语句
  2. 内联函数的定义必须出现在内联函数第一次调用之前;
  3. 类结构中所在的类说明内部定义的函数是内联函数。

C++中的this指针【每个对象都有一个特殊的指针this,指向对象本身】

C++中,this指针是一个特殊的指针,它指向当前对象的实例。
在C++中,每一个对象都能通过this指针来访问自己的地址。
友元函数没有this指针,因为友元不是类的成员,只有成员函数才有this指针。

#include 

class MyClass{
	private:
		int value;

	public:
		void setValue(int value){
			this->value = value;
		}
		void printValue(){
			std::cout << "Value:" << this->value <<std::endl;
		}
};

int main(){
	MyClass obj;
	obj.setValue(42);
	obj.printValue();

	return 0;
}

C++中指向类的指针【指向类的指针方式如同指向结构的指针。实际上,类可以堪称是一个带有函数的结构】

#include 
using namespace std;

class Box{
	public:
		Box(double l=2.0, double b=2.0, double h=2.0){
			cout << "Constructor called." <<endl;
			length = l;
			breadth = b;
			height = h;
		}
		double Volume(){
			return length * breadth * height;
		}
	private:
		double length;
		double breadth;
		double height;
};

int main(){
	Box Box1(3.3, 1.2, 1.5);
	Box Box2(8.5, 6.0, 2.0);
	Box *ptrBox;

	ptrBox = &Box1;
	cout << "Volume of Box1: " << ptrBox->Volume() <<endl;
	
	ptrBox = &Box2;
	cout << "Volume of Box2: " << ptrBox->Volume() <<endl;

	return 0;
}

C++类的静态成员【类的数据成员和函数成员都可以声明为静态的】

可以使用static关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味这无论创建多少个类的对象,静态成员都只有一个副本。

#include 
using namespace std;

class Box{
	public:
		// 静态变量
		static int objectCount;
		// 构造函数定义
		Box(double l=2.0, double b=2.0, double h=2.0){
			cout << "Constructor called." <<endl;
			length = l;
			breadth = b;
			height = h;
			objectCount++;
		}
		double Volume(){
			return length * breadth * height;
		}
	private:
		double length;
		double breadth;
		double height;
};

int Box::objectCount = 0;

int main(){
	Box Box1(3.3, 1.2, 1.5);
	Box Box2(8.5, 6.0, 2.0);

	cout << "Total objects:" << Box::objectCount <<endl;

	return 0;
}

静态成员函数

静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
静态成员函数与普通成员函数的区别:

  • 静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数);
  • 普通成员函数有this指针,可以访问类中的任意成员;而静态成员函数没有this指针。
#include 
using namespace std;

class Box{
	public int objectCount;
		Box(double l=2.0, double b=2.0, double h=2.0){
			cout << "Constructor called." <<endl;
			length = l;
			breadth = b;
			height = h;
			objectCount++;
		}
		double Volume(){
			return length * breadth * height;
		}
		static int getCount(){
			return objectCount;
		}
	private:
		double length;
		double breadth;
		double height;
};

int Box::objectCount = 0;

int main(){
	cout << "Inital Stage Count: " << Box::getCount() <<endl;
	
	Box Box1(3.3, 1.2, 1.5);
	Box Box2(8.5, 6.0, 2.0);

	cout << "Final Stage Count: " << Box::getCount() <<endl;

	return 0;
}

C++继承

基类和派生类

class Animal{
	eat();
	sleep();
};

class Dog : public Animal {
	bark();
};

形式:class derived-class: access-specifier base-class

#include 
using namespace std;

class Shape{
	public:
		void setWidth(int w){
			width = w;
		}
		void setHeight(int h){
			height = h;
		}
	protected:
		int width;
		int height;
};

class Rectangle: public Shape{
	public:
		int getArea(){
			return (width * height);
		}
};

int main(void){
	Rectangle Rect;
	Rect.setWidth(5);
	Rect.setHeight(7);
	cout << "Total area:" << Rect.getArea() <<endl;
	
	return 0;
}

访问控制和继承

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应用在基类中声明为private。
C++冲鸭~【面向对象】_第1张图片

继承类型

当一个类派生自基类,该基类可以被继承为public、protected或private几种类型。继承类型是通过上面讲解的访问修饰符access-specifier来指定的。
我们几乎不适用protected或private,通常使用public继承。

多继承

指一个子类可以有多个父类,它继承了多个父类的特性。
c++类可以从多个类继承成员:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,{
<派生类类体>
};

实例:

#include 
using namespace std;

class Shape{
	public: 
		void setWidth(int w){
			width = w;
		}
		void setHeight(int h){
			height = h;
		}
	protected:
		int weight;
		int height;
};

class PaintCost{
	public:
		int getCost(int area){
			return area * 70;
		}
};

class Rectangle: public Shape, public PaintCost{
	public:
		int getArea(){
			return (width * height);
		}
};

int main(){
	Rectangle Rect;
	int area;

	Rect.setWidth(5);
	Rect.setHeight(7);

	area = Rect.getArea();

	cout << "Total area: " << Rect.getArea() <<endl;
	cout << "Total paint cost: $" << Rect.getCost(area) <<endl;

	return 0;
}

C++重载运算符和重载函数

C++允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是他们的参数列表和定义(实现)不相同。
当调用一个重载函数或重载运算符时,编译器通过把所用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

函数重载

#include 
using namespace std;

class printData{
	public:
		void print(int i){
			cout << "整数为:" << i <<endl;
		}
		void print(double f){
			cout << "浮点数为:" << f <<endl;
		}
		void print(char c[]){
			cout << "字符串为:" << c <<endl;
		}
};

int main(){
	printData pd;
	pd.print(5);
	pd.print(3.6);
	char c[] = "Hello C++";
	pd.print(c);

	return 0;
}

运算符重载

#include 
using namespace std;

class Box{
	public:
		double getVolume(void){
			return length * breadth * height;
		}
		void setLength( double len ){
			length = len;
		}
		void setBreadth( double bre ){
			breadth = bre;
		}
		void setHeight( double hei ){
			height = hei;
		}
		// 重载 + 运算符,用于把两个Box对象相加
		Box operator+(const Box& b){
			Box box;
			box.length = this->length + b.length;
			box.breadth = this->breadth + b.breadth;
			box.heigth = this->height + b.height;
			return box;
		}
	private:
		double length;
		double breadth;
		double heigth;
};

int main(){
	Box Box1;                // 声明 Box1,类型为 Box
    Box Box2;                // 声明 Box2,类型为 Box
    Box Box3;                // 声明 Box3,类型为 Box
    double volume = 0.0;     // 把体积存储在该变量中
 
    // Box1 详述
    Box1.setLength(6.0); 
    Box1.setBreadth(7.0); 
    Box1.setHeight(5.0);
 
    // Box2 详述
    Box2.setLength(12.0); 
    Box2.setBreadth(13.0); 
    Box2.setHeight(10.0);
 
    // Box1 的体积
    volume = Box1.getVolume();
    cout << "Volume of Box1 : " << volume <<endl;
 
   	// Box2 的体积
    volume = Box2.getVolume();
    cout << "Volume of Box2 : " << volume <<endl;
 
    // 把两个对象相加,得到 Box3
    Box3 = Box1 + Box2;
 
    // Box3 的体积
    volume = Box3.getVolume();
    cout << "Volume of Box3 : " << volume <<endl;

	return 0;
}

可重载的运算符/不可重载的运算符

C++冲鸭~【面向对象】_第2张图片
不可重载的运算符:
C++冲鸭~【面向对象】_第3张图片

C++多态

多态:各种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。C++多态意味这调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

#include 
using namespace std;

class Shape{
	protected:
		int width, height;
	public:
		Shape( int a=0, int b=0 ){
			width = a;
			height = b;
		}
		// virtual关键字
		virtual int area(){
			cout << "Parent class area:" <<endl;
			return 0;
		}
};

class Rectangle: public Shape{
	public:
		Rectangle( int a=0, int b=0 ):Shape(a, b){  }
		int area(){
			cout << "Rectangle class area: " <<endl;
			return (width * height);
		}
};

class Triangle: public Shape{
	public:
		Triangle( int a=0, int b=0 ):Shape(a, b){  }
		int area(){
			cout << "Triangle class area: " <<endl;
			return (width * height) / 2;
		}
};

int main(){
	Shape *shape;
	Rectangle rec(10, 7);
	Triangle tri(10, 5);

	shape = &rec;
	shape->area();

	shape = &tri;
	shape->area();

	return 0;
}

每个子类都有一个函数area()的独立实现。多态可以有多个不同的类,都带有同一个名称但具有不同的实现函数,函数的参数甚至可以是相同的。

虚函数

虚函数是在基类中使用关键字virtual声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。动态链接或后期绑定

纯虚函数

在基类中定义虚函数,以便在派生类中重新定义该函数更好的适用于对象,但是基类中又不能对虚函数给出有意义的实现,这时就要用虚函数。

class Shape{
	protected:
		int width, height;
	public:
		Shape( int a=0, int b=0 ){
			width = a;
			height = b;
		}
		// pure virtual function
		virtual int area() = 0;
};

C++数据抽象

数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即可表现必要的信息而不呈现细节。
数据抽象是一种依赖于接口和实现分离的编程技术。

实例:

#include 
using namespace std;

class Adder{
	public:
		// 构造函数
		Adder(int i=0){
			total = i;
		}
		// 对外的接口
		void addNum(int number){
			total += number;
		}
		// 对外的接口
		int getTotal(){
			return total;
		};
	private:
		// 对外隐藏的数据
		int total;
};

int main(){
	Adder a;

	a.addNum(10);
	a.addNum(20);
	a.addNum(30);

	cout << "Total" << a.getTotal() <<endl;

	return 0;
}

C++数据封装

C++程序有两个基本要素:程序语句(代码)和程序数据。

通常情况下,我们都会设置类成员状态为私有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。

这通常应用于数据成员,但它同样适用于所有成员,包括虚函数。

C++接口(抽象类)

接口描述了类的行为和功能,而不需要完成类的特定实现。
C++接口时使用抽象类来实现的,数据抽象是一个把实现细节与相关的数据分离开的概念。

如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 “=0” 来指定的,如下所示:

class Box{
	public:
		virtual double getVolume() = 0;
	private:
		double length;
		double breadth;
		double height;
};

设计抽象类的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。
因此,如果一个 ABC 的子类需要被实例化,则必须实现每个纯虚函数,这也意味着 C++ 支持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导致编译错误。

可用于实例化对象的类被称为具体类。

实例:

#include 
using namespace std;

class Shape{
	public:
		virtual int getArea() = 0;
		void setWidth(int w){
			width = w;
		}
		void setHeight(int h){
			height = h;
		}
	protected:
		int width;
		int heigth;
};

class Rectangle: public Shape{
	public:
		int getArea(){
			retuirn (width * height);
		}
};

class Triangle: public Shape{
	public:
		int getArea(){
			return (width * height) / 2;
		}
};

int main(){
	Rectangle Rect;
	Triangle Tri;
	
	Rect.setWidth(5);
	Rect.setHeight(7);
	cout << "Total Rectangle area: " << Rect.getArea() <<endl;

	Tri.setWidth(5);
	Tri.setHeight(7);
	cout << "Total Triangle area: " << Tri.getArea() <<endl;

	return 0;
}

设计策略
面向对象的系统可能会使用一个抽象基类为所有的外部应用程序提供一个适当的、通用的、标准化的接口。然后,派生类通过继承抽象基类,就把所有类似的操作都继承下来。

外部应用程序提供的功能(即公有函数)在抽象基类中是以纯虚函数的形式存在的。这些纯虚函数在相应的派生类中被实现。

这个架构也使得新的应用程序可以很容易地被添加到系统中,即使是在系统被定义之后依然可以如此。

你可能感兴趣的:(C++冲鸭~,c++,开发语言)