C++ OOP

目录

  • C++ OOP
    • C++ 类
      • class的基本结构
      • class对象的声明与引用
        • 声明
      • 引用
      • 构造函数与析构函数
        • 构造函数
        • 析构函数
      • 类成员
        • public; private; protected
        • inline
        • static数据成员
        • this
        • 嵌套类
        • 局部类
      • friend 友元
      • namespace
        • namespace的定义
        • namespace的使用
    • 继承
      • 访问控制
      • 构造函数,析构函数
        • 当父类存在带参数的构造函数
      • 覆盖父类的成员函数
      • 多重继承
        • 二义性
        • 构造函数调用顺序
    • 多态
    • 运算符重载
      • 允许重载的运算符
      • 例子
      • ++ and - -

C++ OOP

C++ 类

类比结构体增加了操作数据的行为,这个行为就是函数;

class的基本结构

class [类名]
{
	public:
		[数据成员]
		[成员函数]
	protected:
		[数据成员]
		[成员函数]
	private:
		[数据成员]
		[成员函数]
};

另一个类的对象可以作为当前类的成员,但是当前类的对象不能作为该类的成员;
定义class和结构体时,大括号后边要有分号;
class的成员函数可以在class体内实现,也可以在class之外,通过域运算符 :: 实现;
类的数据成员需要初始化,成员函数需要实现代码,但是类的数据成员不能在类的声明中初始化;
允许空class存在 class CppClass{};

class对象的声明与引用

声明

[类名] [对象名称]
CppClass obj_;

引用

[对象名称].[成员名称]
[对象名称].[成员名称](参数表)			//函数引用

[对象指针名]->[成员名称]
(*[对象指针名]).[成员名称]
[对象指针名]->[成员名称](参数表)		//对象指针方式

构造函数与析构函数

构造函数

构造函数是可以带参数的;
构造函数是可以重载的;
复制构造函数:构造函数的参数是一个已经初始化的类的类对象;

析构函数

析构函数名标识符是在类名标识符前面加’~'号;
一个类中只能定义一个析构函数;
析构函数不能重载;
析构函数和构造函数都不能使用return返回值,也不需要void关键字;

类成员

public; private; protected

  • public 的成员对外可见,对内也可见;
  • private 的成员对外不可见,对内可见;
  • protected 的成员对外部可见,对内可见,且对派生类是可见的;

C++ OOP_第1张图片

Reference: http://www.runoob.com/cplusplus/cpp-inheritance.html

inline

class example
{
	private:
		int num;
	public:
		inline void pub_num();
}; 
  • 定义在类体中,即使没有使用inline关键字,该成员函数也会被认为是内联成员函数;

static数据成员

class example
{
	public:
		static unsigned int num; 		//定义静态数据成员
		static void print_num()			//定义静态成员函数
		{
			std::cout << num << std::endl;
		}
};
  • 一个类中的静态数据成员,允许使用类名直接访问example::num = 0;
  • 定义静态数据成员时候,通常需要在类外对静态数据成员进行初始化;
  • 在一个类中,静态数据成员是被所有类对象所共享的,无论存在多少个类的对象,类的静态数据成员始终只有一份;
  • 静态数据成员可以是当前类的类型,其他数据成员只能是当前类的指针或者引用类型?;
  • 静态数据成员可以作为成员函数的默认参数,类的普通数据成员不能作为默认参数;
  • 类的静态成员函数只能访问类的静态数据成员,不能访问普通数据成员;
  • 静态成员函数不能定义为const成员函数,意味着静态成员函数末尾不能使用const关键字;
  • 静态成员函数定义的时候,如果函数的实现代码位于类体之外,则在函数的实现部分不能标识static关键字;

this

  • 为什么需要this指针: 对于类的非静态成员,每一个对象都有自己的一份拷贝,即每个对象都有自己的数据成员,不过成员函数是对象共享的,所以在调用成员函数的时候,需要this指针来区分自己的数据成员,在每个类的成员函数(不包括静态成员函数)中都隐含一个this指针;
  • 待补充

嵌套类

在C++中,允许在一个类中定义另一个类,这叫做嵌套类;

  • 虽然嵌套类是在外部类内部定义的,但是外部类不能访问嵌套类的私有成员;
  • 仅外部类可以使用嵌套类,嵌套类在其他类域或作用域中不可见;
  • 虽然在外部函数中,嵌套类不可见,但是可以通过外部类的类域作为限定符来定义嵌套类out_class::in_class obj_name;

局部类

类的定义不仅可以放在头文件中,也可以放在源文件中,同时也可以放在函数中,这样在函数中定义的类被称为局部类;

  • 在函数之外不可以访问局部类;

friend 友元

使用friend关键字可以定义友元,让特定的函数后者别的类的所有成员函数对本类的私有数据成员进行读写;

namespace

在定义命名空间的时候,通常在头文件中生命命名空间中的函数,在源文件中定义命名空间中的函数;如此使用中,在源文件定义函数时,要使用命名空间名作为前缀;

  • 命名空间可以嵌套;
  • 可以定义未命名的命名空间,未命名的命名空间被设置为全局命名空间;

namespace的定义

namespace [名称]
{
	[常量,变量,函数的定义]
}

namespace的使用

[命名空间名称]::[成员];

也可以使用using namespace语句;

using namespace std;

继承

继承:使得一个类可以从现有的类中派生,而不必定义一个新的类;

class [派生类名]:[继承方式][父类名]		//':'表示子类和父类之间的继承关系;
{
	[访问控制修饰符]:
		[成员声明列表]					//派生类新增的成员;
};
  • 继承方式: public; protected; private;

访问控制

public继承: public -> public; protected -> protected; private -> 不可访问;
protected继承: public -> protected ; protected -> protected; private -> 不可访问;
private继承: public -> private; protected -> private; private -> 不可访问;

构造函数,析构函数

构造函数: 先调用父类的构造函数,然后调用子类的构造函数;
析构函数: 先调用子类的析构函数,然后调用父类的析构函数;

当父类存在带参数的构造函数

默认情况下,子类会调用父类的默认构造函数;
若想使用父类的带参数构造函数,需要显式方式调用父类的构造函数;

覆盖父类的成员函数

如果在子类中定义了一个和父类一样的成员函数,那么一个子类的对象在调用函数的时候,调用的是子类的成员函数;

  • 如果想要访问父类的成员函数,需要显式地使用父类名;

      child_class child_obj;
      child_obj.father_class::father_function();
    
  • 如果子类覆盖了父类的成员函数,则父类中所有的同名成员函数(重载的函数)都会被隐藏;

多重继承

多重继承:子类从多个父类中继承公有和受保护的成员;

class [派生类名] : [继承方式][父类名_1], [继承方式][父类名_2]		//':'表示子类和父类之间的继承关系;子类名之间用','隔开
{
	[访问控制修饰符]:
		[成员声明列表]					//派生类新增的成员;
};

二义性

二义性: 子类在调用成员函数的时候,会先在自身域内寻找,如果找不到,会在基类中寻找,但是当多个父类中有同名成员函数的时候,会不知道调用哪个成员函数,这称为二义性;

  • 可以通过显式的声明来解决

      class child_class : public father_class_1, public father_class_2
      {
      	**** ****
      }
    
      child_class child_obj;
      
      child_obj.father_class_1::father_function();
      child_obj.father_class_2::father_function();
    

构造函数调用顺序

多重继承中构造函数的调用顺序以派生表中的声明顺序为准,调运顺序是按照父类的前后顺序进行的;

  • 派生表是多重继承定义中继承方式后边的内容;

多态

多态: C++中,多态性是指不同功能的函数可以用同一个函数名;

C++有两种联编方式:静态联编,动态联编;根据联编时刻的不同,存在两种不同类型的多态,1: 函数重载; 2: 虚函数;

运算符重载

运算符本质上是一个函数,对运算符的重载也就是对函数的重载;

重载运算符的声明:

operator [类型名]();
  • operator是需要重载的运算符;
  • 运算符重载没有返回值,类型名就代表了返回的类型;
  • 重载运算符不能改变原有运算符的操作数;
  • 重载运算符不能改变原有运算符的优先级;
  • 重载运算符不能改变原有运算符的结合性;
  • 重载运算符不能改变原有运算符的语法结构;

允许重载的运算符

C++ OOP_第2张图片

Reference: http://www.runoob.com/cplusplus/cpp-overloading.html

例子

#include 
using namespace std;
class example
{
	public:
		example(int num_)
		{
			num = num_;
		}
		example operator+(example b)
		{
			return example(num + b.num);
		}
	private:
		int num;
};

void main()
{
	example e_a(1);
	example e_b(2);
	example output(0);
	output = e_a + e_b;
}

++ and - -

对于++和- -运算符;
如果重载运算符没有参数,则表示是前置运算;
如果重载运算符使用整数作为参数,则表示后置运算;

Reference: 《C++从入门到精通》《C++ Primer Plus》

你可能感兴趣的:(C++)