CPP-类定义(Class definitions)

本文详细解释了C++中成员函数和数据成员的声明方式,包括public和private关键字的作用,以及成员函数如何直接访问类的数据成员。同时介绍了成员函数的位置选择、inline函数的概念和应用,以及类的定义与函数定义分开的好处。

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

Member function 的declaration和普通函数一样。仅有的差别是放在类的定义里面。同样数据成员的declaration和普通变量也一样,只是放在类的定义里面。保留字public和private用来实现信息隐藏。public暗示被宣称的属性在类的定义的后续部分是可见的。即到处都可获得。private暗示只能在类的内部获得。 如果没有指明是public或private,类中所有成员默认为private.

C++中成员的宣称可以以任何顺序放置,public 和private也可以任意放置。但通常public放于private之前。

Declaration: what the function is called, what parameters it has, and what result type it returns. 为了使用一个类,成员函数的定义,包括函数的完整实现,必须存在。c++中,有两种方法来定义成员函数,他们可以直接放在内中间,也可以单独放在内的定义之外。例如,我们可以定义如下类:
其中,三个简单函数的实现在类中间,另外三个函数的实现在内之外:

class Clock {
public:
    void set(int hour, int min, int sec);
    int read_hour() {return h;}
    int read_min() { return m;}
    int read_sec() { return s;}
    void write(bool write_sec = true);
    void tick();
private:
    int h, m, s;
};

void Clock::set(int hour, int min, int sec)
{
    h = hour; m = min; s = sec;
}
void Clock::write(bool write_sec)
{
    cout << setw(2) << setfill('0') << h
        << ':' << setw(2) << setfill('0') << m;
    if (write_sec)
        cout << ':' << setw(2) << setfill('0') << s;
}
void Clock::tick()
{
    s = (s + 1) % 60;
    if (s == 0)
    {
        m = (m + 1) % 60;
        if (m == 0)
            h = (h + 1) % 24;
    }
}

注意尽管数据成员没有在成员函数中定义,也没有作为亚元传递给成员函数,但成员函数能够直接访问数据成员,但这只局限在成员函数。如果我们有另外一个函数,并不是类Clock的成员函数,那么就不能访问h,m和s. 当在一个成员函数内使用数据成员名字时,暗示数据成员属于当时成员函数被调用的类。成员函数不是普通函数,他们有独特的性质。例如:成员函数能直接访问类中的数据成员。当成员函数在所属类的外部被定义时,不能直接写成员函数的名字,必须指明此成员函数属于那个类。
在类的内部直接定义成员函数显得很方便,由于写的东西较少,但也应该小心,因为程序的可读性会降低。
关于成员函数的位置,另外一些事情也必须清楚,这和c++编译器如何将成员函数转变为机器骂有关。当调用一个函数时候(适用普通函数和成员函数),编译器通常产生机器码,这意味着程序要跳转到函数代码的位置,当函数机器码执行完毕,程序要跳转回调用的地方。函数机器码本身只存在于一个地址,因此所有调用都导致跳转到该地址。因此在每次调用时候必须有些指令保证程序的正确跳转和参数的正确传递。如果一个程序极其简单,只包含一条或两条语句,很可能这些额外指令比函数本身更复杂并要求更多的内存空间。此时,最好的情况是不执行跳转,而让程序在调用的地方直接开始执行,这种函数是inline function. inline function的代码在程序中所有调用的地方重复。
成员函数经常很简短,因此最好定义为inline function.如果成员函数的定义直接在类的内部,那么编译器默认将这些函数变为inline function. 由于比较长的函数不被认为是inline,因此,在类的内部定义多余几条语句的函数是不恰当的。这些函数应该单独定义。
将类的定义和函数定义分开还有其他好处,即使需要多书写代码,例如,程序看起来更好,更容易懂。依次所有函数应该在类的外部定义,即使函数很简短。如果我们想让函数成为inline, 我们总能用在函数定义时候使用inline。

例如:

inline void Clock::set(int hour,int min,int sec)
{
    h=hour;m=min;s=sec;
}
### C++ 枚举多重公共定义错误解决方案 当遇到 `C++` 中枚举型的多重公共定义(`MULTIPLE PUBLIC DEFINITIONS`)编译错误时,通常是因为头文件被多次包含而未采取预防措施。为了避免此问题的发生,在声明枚举型时应遵循良好的编程实践。 #### 使用预处理指令防止重复包含 通过在头文件中使用预处理器指令可以有效避免同一文件被多次引入造成的冲突: ```cpp #ifndef ENUM_HEADER_H_ #define ENUM_HEADER_H_ enum Color { RED, GREEN, BLUE }; #endif // ENUM_HEADER_H_ ``` 这种方式确保即使同一个头文件在一个项目里被多个源文件引用也只会实际加载一次[^1]。 #### 将枚举定义置于命名空间内 为了进一步减少名称冲突的可能性,建议将枚举放置于特定的命名空间之下: ```cpp namespace MyNamespace { enum Direction { NORTH, SOUTH, EAST, WEST }; } // namespace MyNamespace ``` 这样做不仅有助于区分不同模块之间的同名实体,同时也提高了代码可读性和维护性[^2]。 #### 利用匿名命名空间或静态关键字限定作用域 对于仅限单个翻译单元使用的枚举变量,可以通过匿名命名空间或者给成员加上`static`修饰符来限制其可见范围: ```cpp // 匿名命名空间方式 namespace { enum InternalState { IDLE, RUNNING, STOPPED }; } class MyClass { public: private: static enum Status { OK, ERROR } status_; }; ``` 上述方法能够有效地控制符号的作用域,从而降低发生重定义的风险[^3]。 #### 应用现代C++特性 自C++11起支持强型枚举(`enum class`),这使得枚举更加安全可靠,并且不会与其他全局名字产生混淆: ```cpp enum class Month : int { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER }; ``` 这种形式增强了型安全性并减少了意外转换带来的隐患[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值