C/C++编程:成员函数

1060 篇文章 299 订阅

什么是成员函数

在类中声明的函数就叫做成员函数

考虑用struct实现日期的概念:定义Date的表示方式和操作这种类型的变量的一组函数:

struct Date{
	int d, m, y;
};

void init_date(Date &d, int, int, int);  //初始化
void add_year(Date &d, int );
void add_month(Date &d, int );
void add_day(Date &d, int );

数据类型,Date和这些函数之间并无显式关联。我们可以通过将函数声明为成员来建立这种关联:

struct Date{
	int d, m, y;

	//成员函数
	void init_date( int, int, int);  //初始化
	void add_year(int );
	void add_month(int );
	void add_day( int );
};

由于不同结构可能有同名成员函数,在定义成员函数时必须指定结构名

void Date::init_date( int yy, int mm, int dd){
	y = yy;
	m = mm;
	d = dd;
}

分类

静态/非静态

成员函数是静态或非静态的。

静态成员函数

语法:
在这里插入图片描述
说明:

  • 静态成员函数不关联到任何对象。调用时,它们无 this 指针。
  • 它只能访问类的静态数据成员
  • 静态成员函数不能为 virtual、const 或 volatile。
  • 静态成员函数的地址可以存储在常规的函数指针中,但不能存储于成员函数指针中。

非静态成员函数

  • 非静态成员函数是声明于类的成员说明中,不带 static 或 friend 说明符的函数。
class S {
    int mf1(); // 非静态成员函数声明
    void mf2() volatile, mf3() &&; // 可为 cv 限定或引用限定
    int mf4() const { return data; } // 可内联定义
    virtual void mf5() final; // 可为虚函数,可使用 final/override
    S() : data(12) {} // 构造函数亦是成员函数
    int data;
};
int S::mf1() { return 7; } // 若不内联定义,则必须定义于命名空间

总结:静态成员函数的行为与其他成员函数的行为不同,因为静态成员函数没有隐式this自变量。 非静态成员函数具有 this指针。

内联/非内联

内联成员函数

成员函数的定义可以在类中实现,也可以在类外实现(无论是静态的还是非静态的)。

如果在类声明的内部定义一个成员函数,那么该函数会被视为内联函数,并且不需要用其类名来限定函数名称。当然,我们也可以用inline来显式标记这是一个内联函数

class Account
{
public:
    // Deposit是一个内联成员函数
    double Deposit( double HowMuch )
    {
        balance += HowMuch;
        return balance;
    }
private:
    double balance;
};

int main()
{
}

如果成员函数的定义在类声明的外部,则仅当它显式声明为时,才会将其视为内联函数 inline 。 此外,必须通过范围解析运算符 (:😃 用类名称限定定义中的函数名称。

如果下面例子与上面的等效

class Account
{
public:
    //声明但是不定义
    double Deposit( double HowMuch );
private:
    double balance;
};

inline double Account::Deposit( double HowMuch )
{
    balance += HowMuch;
    return balance;
}

int main()
{
}

包含成员函数的类可具有多个声明,但成员函数本身只能在程序中有一个定义。 多个定义会导致在链接时出现错误消息。 如果类包含内联函数定义,则这些函数定义必须与遵守此“一个定义”规则相同。

非内联成员函数

三个说明符

virtual说明符

virtual关键字只能用于非静态类成员函数。它表示函数的绑定将推迟到允许时。具体参见虚拟函数

在传统C++中,经常容易发生意外重载虚函数的事情,比如:

struct Base{
	virtual void f00();
};

struct SubClass:Base{
	void f00();
};

SubClass:foo可能不是程序员尝试重载虚函数,只是恰好加入了一个具有相同名字的函数。另一个可能的情况是,当基类的虚函数被删除后,子类拥有的旧的函数不再重载虚函数而变成了一个普通的类方法,这将造成灾难性后果

override说明符

override关键字用来指定在基类中重写虚函数的成员函数:当重载虚函数时,引入override关键字将显式的告知编译器进行重载,编译器将检查基函数是否存在这种的虚函数,否则将无法通过编译

struct Base{
	virtual void foo(int);
};

struct SubClass : Base{
	virtual void foo(int) override;  //合法
	virtual void foo(float) override; //非法,父类没有此虚函数
};

作用

使用override有助于防止出现意外的继承行为。下面的示例演示在不使用重写的情况下,可能尚未设计派生类的成员函数行为。编译器不会发出此代码的任何错误:

class BaseClass{
    virtual void funcA();
    virtual void funcB() const;
    virtual void funcC(int = 0);
};

class DerivedClass : public BaseClass{
    virtual void funcA();   // ok,按照预期的方式工作
    virtual void funcB();  // DerivedClass::funcB()是非 non-const, 所以它没有
                           // 重写virtual void funcB() const, 它是一个新的成员函数
    virtual void func(double = 0.0);   // 相比BaseClass::funcC(int),  DerivedClass::funcC(double)
                                       //的形参不同,所以它是一个新成员成员
};

使用override时,编译器会生成错误,而不是以无提示方式创建新的成员

class BaseClass
{
    virtual void funcA();
    virtual void funcB() const;
    virtual void funcC(int = 0);
    void funcD();
};

class DerivedClass: public BaseClass
{
    virtual void funcA() override; // ok

    virtual void funcB() override; // 编译错误:DerivedClass::funcB()不重写BaseClass::funcB() const

    virtual void funcC( double = 0.0 ) override; // 编译错误:DerivedClass::funcC(double) 不重写BaseClass::funcC(int)

    void funcD() override; // 编译错误: DerivedClass::funcD() 不重写非虚 BaseClass::funcD()
};

若要指定不能重写函数以及无法继承类,请使用final关键字

final 说明符

finial时为了防止类被继续继承而终止虚函数继续重载引入的。
在这里插入图片描述

  • final指定不能在派生类中重写的虚函数(override指定可以重写成员函数的信息)
class BaseClass
{
    virtual void func() final;
};

class DerivedClass: public BaseClass
{
    virtual void func(); // compiler error: attempting to
                         // override a final function
};
  • 指定无法继承的类。
class BaseClass final
{
};

class DerivedClass: public BaseClass // compiler error: BaseClass is
                                     // marked as non-inheritable
{
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值