C++入门小知识(二)const修饰成员函数,内联函数,有元,静态成员的理解

本文深入探讨了C++中的const修饰成员函数、内联函数、友元及静态成员的概念与应用,通过实例解析了这些特性如何增强代码的功能性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c++入门小知识总结(二)

const修饰的成员函数

如果学过C语言,那么对const有一定的了解,const修饰的变量不能能够被改变,修饰指针呢,指针不能被改变等。。。
在C++中const修饰的成员函数,那么可以推测一下,是不是它所修饰的成员函数不能改变呢?答案是no 不是说它所修饰的成员函数不能被改变,而是它所要接受的对象在本函数中不能不改变。
怎么来修饰成员函数呢?
举个例子:

class Date
{
public:
void Print()const // 这就是const修饰的成员函数
{
    cout << _year << "-" << _month << "-" << _day << endl;
}
private:
    int _year;
    int _month;
    int _day;
};

用const修饰的成员函数在传对象的时候可以传非const修饰的对象,也可以传被const修饰的对象。
如果被const修饰的对象,就不能传给没有被const修饰的成员函数。
在这里总结,被const修饰的权限小,而没修饰的权限大,记住权限只能缩小,不能放大。在传参的过程中。

内联函数

关键字inline
被inline修饰的函数叫内敛函数。内敛函数一般在编译的时候会将函数展开,美誉压栈的开销,是一种空间换时间的做法,提高了代码的运行速率,但代码量加大。
这里有三点需要注意:

  1. 在对函数进行修饰为inline时,这时只是对编译器的一个建议,编译器可以采用,也可以不采用。如果定义的内敛函数出现在循环递归等重复性比较高的时候,编译器会自动优化,把inline函数变成一般函数。
  2. inline必须和函数定义放在一块才能生效,如果和声明放在一块是不会有作用。
  3. 如果在定义函数时放在类里面定义,那么系统会自动的默认为内敛函数,但是具体是否被当作内敛函数所执行,那就看编译器是如何优化的。

关于内敛函数的用途我们还可以想到#define宏函数。它也是一种空间换时间的做法。但是两者又有很多差异。
我们来分析一下它们的优缺点:
优点:
内敛函数:提高了代码的运行效率。代码可以进行调试。有了类型的检查。
宏:提高了代码的运行效率,可以代替单个变量。
缺点:
内敛函数:不能代替单个变量,受到编译器的限制
宏:不方便调试,代码可读性差,维护性差,容易误用,没有类型检查。

友元

友元函数
友元函数说明:友元函数在类外允许访问类中的任何成员。关键字friend
注意两点:

  1. 友元函数不是类的成员函数,所以不能通过类来访问友元函数。
  2. 友元函数可以通过对象访问所有成员,包括私有的和保护的。

友元函数使用声明友元函数必须在类的public并且需要加上friend关键字。
函数定义处不用添加关键字friend
例如:

class Date
{
public:
    friend void Print();
private:
    int _year;
    int _month;
    int _day;
};
void Print()
{
    cout << _year << "-" << _month << "-" << _day << endl;
}

上面的void Print()函数就是一个友元函数。
在类外面定义的函数,是Date类的友元函数,那么类外的函数就可以直接访问类里面的成员变量,不管是受到保护的还是私有的。
友元类
一个类可以成为另一个类的友元类,那么这个类的所有成员函数都是另一个类的友元函数。
我们来举个例子:

class Date
{
private:
    int _year;
    int _month;
    int _day;
};
class Time
{
public:
    friend class Date;
private:
    int _hour;
    int _minute;
    int _second;
};

这里的Date类就是Time;类的友元类,Date的所有成员函数都是Time类的友元函数。
在面向对象编程中有三大特性:封装, 继承, 多态。
但是友元破环了封装性,所以尽量少用。

静态成员

类的静态成员变量
静态成员关键字static 在所需要定义的变量或者函数前面加上关键字。
静态成员变量是该类的所有对象的共享成员变量。所以在类中初始化静态成员变量时,不能在构造函数中初始化静态成员变量。
例如:

class Date
{
private:
    int _year;
    int _month;
    static int _count;
    int _day;
};
// 静态变量的初始化
int Date::_count = 0;

静态成员函数
静态成员函数也是所有对象共享的。
要注意的是静态成员函数没有隐含的this指针,所以在调用静态成员函数时,直接用类名加域符号和静态成员函数。
比如:

ass Date
{
public:
    static void Print()
    {
    cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    // 静态成员函数的调用
    Date::Print();
    return 0;
}

这里还有两点
静态成员函数不可以访非静态成员(没有this指针)
非静态成员函数可以访问静态成员

<think>好的,我现在需要帮助用户了解C++静态成员函数在.h和.cpp文件中的声明与定义方法。首先,我应该回忆一下C++中类的静态成员函数的基本概念。静态成员函数是属于类而不是类的实例的,它们不能访问非静态成员变量或函数。接下来,我需要确定如何在头文件(.h)和源文件(.cpp)中正确声明和定义这些静态成员函数。 根据引用[4],类的定义通常放在.h文件中,包括类函数成员和数据成员的声明。对于静态成员函数,它们的声明应该在类的定义内部,也就是在.h文件中,使用static关键字。例如: class MyClass { public: static void myStaticFunction(); }; 然后,静态成员函数的定义通常放在.cpp文件中,但不需要再次使用static关键字。例如: void MyClass::myStaticFunction() { // 实现代码 } 这里需要注意的是,如果在头文件中定义静态成员函数,可能会导致多重定义的错误,尤其是在多个源文件包含该头文件时。因此,定义应该放在.cpp文件中。 另外,引用[5]提到,头文件在预处理阶段被包含到源文件中,编译时编译器检查声明,而链接器在链接阶段处理定义。因此,将定义放在.cpp中可以避免链接错误。 还有一种特殊情况,如果静态成员函数是内联的,可以在.h文件中使用inline关键字定义,这样可以在多个编译单中使用而不会引发链接错误。例如: // 在.h文件中 class MyClass { public: static inline void myInlineStaticFunction() { // 内联实现 } }; 不过,用户的问题主要是关于静态成员函数的标准声明和定义方式,所以重点应放在普通的静态函数上,内联的情况可以作为补充说明。 总结步骤: 1. 在.h文件的类声明中声明静态成员函数,使用static关键字。 2. 在.cpp文件中定义该函数,省略static关键字,使用类名限定。 3. 避免在头文件中定义非内联的静态成员函数,以防止多重定义错误。 同时需要引用相关的参考资料来支持这些步骤,特别是引用[4]和[5],因为它们提到了头文件和源文件中的内容安排以及编译链接过程。 可能还需要提醒用户关于模板静态成员函数的处理,但用户的问题可能不涉及模板,所以暂时作为扩展内容。 最后,生成相关问题,涉及静态成员变量、内联函数、模板处理等,确保问题与主题相关,并引导进一步学习。</think>### C++静态成员函数在.h和.cpp文件中的声明与定义方法 在C++中,静态成员函数的声明与定义需遵循**声明在头文件、实现在源文件**的原则,具体操作如下: --- #### **1. 头文件(.h)中的声明** 在类的定义内部声明静态成员函数时,需使用`static`关键字,**不包含函数体**: ```cpp // MyClass.h class MyClass { public: static void staticFunc(); // 声明静态成员函数 static inline void inlineStaticFunc() { /* 内联实现 */ } // 内联函数可直接在头文件定义 }; ``` - **关键规则**:静态成员函数声明必须包含`static`关键字[^4]。 - **例外情况**:若需在头文件中直接实现,必须添加`inline`关键字以避免多重定义错误[^4]。 --- #### **2. 源文件(.cpp)中的定义** 在源文件中定义静态成员函数时,**省略`static`关键字**,但需通过类名限定作用域: ```cpp // MyClass.cpp #include "MyClass.h" void MyClass::staticFunc() { // 正确:省略static,用类名限定 // 函数实现 } ``` - **禁止操作**:在.cpp中重复使用`static`关键字(会导致编译错误)[^4]。 - **链接逻辑**:源文件编译后生成目标文件,链接器通过类名和作用域解析符号[^5]。 --- #### **3. 静态成员变量的特殊处理** 若静态成员函数操作静态成员变量,需注意: - **变量声明**:在.h文件的类内部用`static`声明变量。 - **变量定义**:在.cpp文件中单独定义(即使变量是`const`类型): ```cpp // MyClass.h class MyClass { private: static int s_value; // 声明静态成员变量 }; // MyClass.cpp int MyClass::s_value = 42; // 必须单独定义 ``` --- #### **4. 模板类的静态成员函数** 对于模板类,静态成员函数的定义通常需要**直接在头文件中实现**: ```cpp // MyTemplate.h template <typename T> class MyTemplate { public: static void templateStaticFunc() { // 必须内联实现 // 函数体 } }; ``` - **原因**:模板的实例化依赖编译器在编译时生成代码。 --- #### **常见错误示例** - **错误1**:在.cpp中使用`static`重复修饰: ```cpp static void MyClass::staticFunc() {} // 错误:多余的static ``` - **错误2**:在.h文件中无`inline`定义非内联函数: ```cpp // MyClass.h static void MyClass::staticFunc() {} // 错误:多重定义风险 ``` --- ### 相关问题 1. 静态成员变量在.h和.cpp中如何声明和定义? 2. 为什么模板类的静态成员函数必须定义在头文件中? 3. 内联静态成员函数与普通静态成员函数有何区别? 4. 如何在静态成员函数中访问非静态成员变量?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值