類別 = 資料 + 行為的封裝單元
類別是使用者自訂型別,包含成員變數(資料屬性)與成員函數(行為操作),二者統稱「成員」。
成員變數:宣告而非定義
class Student {
public:
char* name; // 僅宣告型別與名稱
int age;
float score;
};
- **不佔記憶體**:類別本身是模板,不分配儲存空間。
- **不可在類內初始化**(C++11 前):
int age = 18; 非法(C++11 起允許非靜態資料成員預設初始化)。
- 物件建立時,各物件擁有獨立副本,佔用
sizeof(Student) 位元組。
成員函數:類內宣告、類外定義(推薦)
// 類別宣告(通常置於 .h)
class Student {
public:
char* name;
int age;
float score;
void say(); // 僅宣告
};
// 類外定義(通常置於 .cpp)
void Student::say() { // 必須加 類別名::
cout << name << " 年齡 " << age << " 成績 " << score << endl;
}
:: 為**域解析運算子**,指明函數隸屬哪個類別。
- 類內直接定義會**隱式成為 inline 函數**;類外定義預設非 inline。
- 實務建議:類內宣告、類外定義,分離介面與實現,避免不必要的內聯膨脹。
inline 成員函數:效能與編譯依賴的權衡
| 定義位置 | 是否 inline | 優點 | 缺點 |
| 類內直接定義 | 隱式 inline | 簡潔、調用零開銷 | 修改實現需重編譯所有包含檔、程式碼膨脹 |
| 類外定義 + inline | 顯式 inline | 可控制哪些函數內聯 | 定義必須置於頭文件(編譯期需可見函數體) |
| 類外定義(無 inline) | 非 inline | 介面與實現分離、編譯防火牆 | 函數呼叫開銷 |
何時使用 inline?
- 極短小、高頻呼叫的函數(getter/setter、簡單運算)。
- 模板函數、模板類別成員(定義必須在頭文件)。
原則:預設類外定義(非 inline),經效能分析證實為熱點再加 inline。現代編譯器(開啟 LTO)跨檔案也能內聯,手動 inline 重要性降低。
完整範例:分離宣告與定義
// Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
class Student {
public:
Student(const std::string& name, int age, float score);
void show() const;
const std::string& getName() const;
int getAge() const;
float getScore() const;
private:
std::string m_name;
int m_age;
float m_score;
};
#endif
// Student.cpp
#include "Student.h"
#include <iostream>
Student::Student(const std::string& name, int age, float score)
: m_name(name), m_age(age), m_score(score) { }
void Student::show() const {
std::cout << m_name << " 年齡 " << m_age << " 成績 " << m_score << '\n';
}
const std::string& Student::getName() const { return m_name; }
int Student::getAge() const { return m_age; }
float Student::getScore() const { return m_score; }
總結
- 成員變數:類內宣告,物件建立時分配記憶體,各物件獨立副本。
- 成員函數:類內宣告,建議類外定義(非 inline),必要時加
inline 置於頭文件。
:: 連接類別與成員,實現作用域隔離。
- 分離介面(.h)與實現(.cpp)是專業 C++ 開發的基本功。
- 上一篇文章: C++ 類別成員存取權限詳解
- 下一篇文章: C++ 類別定義與物件建立完整指南
Copyright ©
程式碼之家 All Rights Reserved