友元函数类图_C++ 虚函数和纯虚函数 virtual 友元函数和友元类 override const

本文详细介绍了C++中的虚函数、纯虚函数的概念和使用,强调了虚函数在多态性中的作用。同时,讲解了const修饰的成员函数及其限制,并探讨了友元函数和友元类的功能与注意事项,以及C++11中关于默认函数的控制特性。通过实例展示了虚函数和多态性的应用,帮助读者深入理解C++的面向对象特性。
摘要由CSDN通过智能技术生成

1)  公有继承

纯虚函数      => 继承的是:接口 (interface)

普通虚函数   => 继承的是:接口 + 缺省实现 (default implementation)

非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)

2)  不要重新定义一个继承自基类的非虚函数(never redefine an inherited non-virtual function)

3)  override:可以显式的在派生类中声明,哪些成员函数需要被重写,如果没被重写,则编译器会报错。

const修饰成员函数

(1)该成员函数不能修改任何的成员变量(mutable修饰的变量除外)

(2)该成员函数不能调用非const成员函数,因为非const成员函数可能会修改成员变量

virtual

虚函数是在基类中使用关键字 virtual 声明的函数,虚函数最关键的特点是“动态联编”,它可以在运行时判断指针指向的基类或子类对象,并自动调用类型的成员函数。

纯虚函数  :virtual int area() = 0;

通常通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。换句话说,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态。

#include

using namespace std;

//基类People

class People{

public:

People(char *name, int age);

void display();

protected:

char *m_name;

int m_age;

};

People::People(char *name, int age): m_name(name), m_age(age){}

void People::display(){

cout<

}

//派生类Teacher

class Teacher: public People{

public:

Teacher(char *name, int age, int salary);

void display();

private:

int m_salary;

};

Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}

void Teacher::display(){

cout<

}

int main(){

People *p = new People("王志刚", 23);

p -> display();

p = new Teacher("赵宏佳", 45, 8200);

p -> display();

return 0;

}

王志刚今年23岁了,是个无业游民。

赵宏佳今年45岁了,是个无业游民。

我们直观上认为,如果指针指向了派生类对象,那么就应该使用派生类的成员变量和成员函数,这符合人们的思维习惯。但是本例的运行结果却告诉我们,当基类指针 p 指向派生类 Teacher 的对象时,虽然使用了 Teacher 的成员变量,但是却没有使用它的成员函数,导致输出结果不伦不类(赵宏佳本来是一名老师,输出结果却显示人家是个无业游民),不符合我们的预期。

换句话说,通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。为了消除这种尴尬,让基类指针能够访问派生类的成员函数,C++ 增加了虚函数(Virtual Function)。使用虚函数非常简单,只需要在函数声明前面增加 virtual 关键字。

#include

using namespace std;

//基类People

class People{

public:

People(char *name, int age);

virtual void display(); //声明为虚函数

protected:

char *m_name;

int m_age;

};

People::People(char *name, int age): m_name(name), m_age(age){}

void People::display(){

cout<

}

//派生类Teacher

class Teacher: public People{

public:

Teacher(char *name, int age, int salary);

virtual void display(); //声明为虚函数

private:

int m_salary;

};

Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}

void Teacher::display(){

cout<

}

int main(){

People *p = new People("王志刚", 23);

p -> display();

p = new Teacher("赵宏佳", 45, 8200);

p -> display();

return 0;

}

运行结果:

王志刚今年23岁了,是个无业游民。

赵宏佳今年45岁了,是一名教师,每月有8200元的收入。

int main(){

People p("王志刚", 23);

Teacher t("赵宏佳", 45, 8200);

People &rp = p;

People &rt = t;

rp.display();

rt.display();

return 0;

}

由于引用类似于常量,只能在定义的同时初始化,并且以后也要从一而终,不能再引用其他数据,所以本例中必须要定义两个引用变量,一个用来引用基类对象,一个用来引用派生类对象。从运行结果可以看出,当基类的引用指代基类对象时,调用的是基类的成员,而指代派生类对象时,调用的是派生类的成员。

不过引用不像指针灵活,指针可以随时改变指向,而引用只能指代固定的对象,在多态性方面缺乏表现力,所以以后我们再谈及多态时一般是说指针。本例的主要目的是让读者知道,除了指针,引用也可以实现多态。

多态使用:

#include

using namespace std;

class Troops{

public:

virtual void fight(){ cout<

};

//陆军

class Army: public Troops{

public:

void fight(){ cout<

};

class _99A: public Army{

public:

void fight(){ cout<

};

class WZ_10: public Army{

public:

void fight(){ cout<

};

class CJ_10: public Army{

public:

void fight(){ cout<

};

//空军

class AirForce: public Troops{

public:

void fight(){ cout<

};

class J_20: public AirForce{

public:

void fight(){ cout<

};

class CH_5: public AirForce{

public:

void fight(){ cout<

};

class H_6K: public AirForce{

public:

void fight(){ cout<

};

int main(){

Troops *p = new Troops;

p ->fight();

//陆军

p = new Army;

p ->fight();

p = new _99A;

p -> fight();

p = new WZ_10;

p -> fight();

p = new CJ_10;

p -> fight();

//空军

p = new AirForce;

p -> fight();

p = new J_20;

p -> fight();

p = new CH_5;

p -> fight();

p = new H_6K;

p -> fight();

return 0;

}

virtual type () const=0

成员函数后面用 const 修饰,通俗的理解就是在这个函数内不能修改类的成员变量,除非那个成员变量是   mutable   的

virtual void print() const = 0;

(1)=0说明它是纯虚函数,没有定义,只有接口,由子类继承实现

(2)const表明不能修改其数据成员

class aa{

int num;

public:

aa(){

int b =10;

num = b;

};

void out1(){

cout<

}

void out2() const{

cout<

}

void out3() const{

num+=10; //出错,const函数不能修改其数据成员

cout<

}

}

友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。

友元函数 :

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:

friend 类型 函数名(形式参数);

友元类 :

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。

当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

friend class 类名;

其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

使用友元类时注意:

(1)友元关系不能被继承。

(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

inline 避免了频繁调用函数对栈内存重复开辟所带来的消耗,比如递归函数,inline仅是一个对编译器的建议 inline的使用是有所限制的,inline只适合函数体内代码简单的函数使用,不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。

c++11 类默认函数的控制:"=default" 和 "=delete"函数

C++ 的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。

这些类的特殊成员函数负责创建、初始化、销毁,或者拷贝类的对象。

如果程序员没有显式地为一个类定义某个特殊成员函数,而又需要用到该特殊成员函数时,则编译器会隐式的为这个类生成一个默认的特殊成员函数。

C++11 标准引入了一个新特性:"=default"函数。程序员只需在函数声明后加上“=default;”,编译器将为显式声明的 "=default"函数自动生成函数体。

"=default"函数特性仅适用于类的特殊成员函数,且该特殊成员函数没有默认参数。

"=default"函数既可以在类体里(inline)定义,也可以在类体外(out-of-line)定义。

class X

{

public:

X() = default; //该函数比用户自己定义的默认构造函数获得更高的代码效率

}

// 为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:"=delete"函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。

class X3

{

public:

X3();

X3(const X3&) = delete; // 声明拷贝构造函数为 deleted 函数

X3& operator = (const X3 &) = delete; // 声明拷贝赋值操作符为 deleted 函数

};

// "=delete"函数特性还可用于禁用类的某些转换构造函数,从而避免不期望的类型转换

class X4

{

public:

X4(double)

{

}

X4(int) = delete;

};

// "=delete"函数特性还可以用来禁用某些用户自定义的类的 new 操作符,从而避免在自由存储区创建类的对象

class X5

{

public:

void *operator new(size_t) = delete;

void *operator new[](size_t) = delete;

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值