C++ 类成员
在C++面向对象编程中,类是创建对象的蓝图或模板。类成员是构成类的基本元素,它们定义了类的数据和行为。理解类成员对于掌握C++面向对象编程至关重要。
类成员的基本概念
类成员主要分为两种类型:
- 数据成员:存储类对象的状态信息(变量)
- 成员函数:定义类对象可以执行的操作(方法)
让我们通过一个简单的例子来理解类成员:
#include <iostream>
#include <string>
using namespace std;
// 定义一个学生类
class Student {
private:
// 数据成员
string name;
int age;
double grade;
public:
// 成员函数
void setInfo(string n, int a, double g) {
name = n;
age = a;
grade = g;
}
void displayInfo() {
cout << "姓名: " << name << endl;
cout << "年龄: " << age << endl;
cout << "成绩: " << grade << endl;
}
};
int main() {
Student s1;
s1.setInfo("张三", 18, 92.5);
s1.displayInfo();
return 0;
}
输出结果:
姓名: 张三
年龄: 18
成绩: 92.5
在上面的例子中,Student
类包含:
- 数据成员:
name
、age
和grade
- 成员函数:
setInfo()
和displayInfo()
访问控制与访问修饰符
C++提供了三种访问修饰符来控制类成员的可访问性:
- public:可以被类外的任何函数访问
- private:只能被类内的成员函数访问
- protected:只能被类内的成员函数和派生类的成员函数访问
如果没有指定访问修饰符,类的成员默认为private。
class Box {
public:
double getVolume() {
return length * width * height;
}
void setDimensions(double l, double w, double h) {
length = l;
width = w;
height = h;
}
private:
double length;
double width;
double height;
};
成员函数详解
在类内定义成员函数
如上面的例子所示,我们可以直接在类定义内部实现成员函数。
在类外定义成员函数
我们也可以在类外定义成员函数,这样可以使类的定义更加简洁:
class Circle {
private:
double radius;
public:
void setRadius(double r);
double getArea();
};
// 在类外定义成员函数
void Circle::setRadius(double r) {
radius = r;
}
double Circle::getArea() {
return 3.14159 * radius * radius;
}
在类外定义成员函数时,需要使用作用域解析运算符(::
)来指明该函数属于哪个类。
构造函数和析构函数
构造函数
构造函数是一种特殊的成员函数,在创建类的新对象时自动调用。构造函数与类同名且没有返回类型。
class Rectangle {
private:
double width;
double height;
public:
// 默认构造函数
Rectangle() {
width = 0.0;
height = 0.0;
}
// 带参数的构造函数
Rectangle(double w, double h) {
width = w;
height = h;
}
double getArea() {
return width * height;
}
};
int main() {
Rectangle rect1; // 使用默认构造函数
Rectangle rect2(5.0, 3.0); // 使用带参数的构造函数
cout << "矩形1的面积: " << rect1.getArea() << endl;
cout << "矩形2的面积: " << rect2.getArea() << endl;
return 0;
}
输出结果:
矩形1的面积: 0
矩形2的面积: 15
析构函数
析构函数是另一种特殊的成员函数,在对象被销毁时自动调用。析构函数与类同名,但前面有一个波浪号(~
),且没有返回类型和参数。
class DynamicArray {
private:
int* data;
int size;
public:
// 构造函数
DynamicArray(int sz) {
size = sz;
data = new int[size]; // 动态分配内存
cout << "构造函数: 分配了内存" << endl;
}
// 析构函数
~DynamicArray() {
delete[] data; // 释放内存
cout << "析构函数: 释放了内存" << endl;
}
void setValue(int index, int value) {
if(index >= 0 && index < size)
data[index] = value;
}
int getValue(int index) {
if(index >= 0 && index < size)
return data[index];
return -1;
}
};
void testDynamicArray() {
DynamicArray arr(5);
arr.setValue(0, 10);
cout << "arr[0] = " << arr.getValue(0) << endl;
// 函数结束时,arr会被销毁,析构函数会被调用
}
int main() {
testDynamicArray();
cout << "函数已返回" << endl;
return 0;
}
输出结果:
构造函数: 分配了内存
arr[0] = 10
析构函数: 释放了内存
函数已返回
静态类成员
静态数据成员
静态数据成员是属于类而不是对象的变量。无论创建多少个对象,静态数据成员只有一个副本。
静态成员函数
静态成员函数是不依赖于任何对象的函数。它们不能访问非静态数据成员,只能调用其他静态成员函数。
class Account {
private:
static double interestRate; // 静态数据成员声明
double balance;
public:
Account(double b) : balance(b) {}
// 静态成员函数
static void setInterestRate(double rate) {
interestRate = rate;
}
static double getInterestRate() {
return interestRate;
}
double calculateInterest() {
return balance * interestRate;
}
};
// 静态数据成员定义和初始化
double Account::interestRate = 0.05;
int main() {
Account::setInterestRate(0.06); // 可以通过类名访问静态成员函数
Account acc1(1000.0);
Account acc2(2000.0);
cout << "利率: " << Account::getInterestRate() << endl;
cout << "账户1利息: " << acc1.calculateInterest() << endl;
cout << "账户2利息: " << acc2.calculateInterest() << endl;
return 0;
}
输出结果:
利率: 0.06
账户1利息: 60
账户2利息: 120
静态数据成员需要在类外进行定义和初始化(除了const整型静态数据成员外)。
const成员函数
const成员函数是不会修改对象状态的函数。在函数声明中,const
关键字放在函数参数列表之后。
class Temperature {
private:
double celsius;
public:
Temperature(double c) : celsius(c) {}
// const成员函数
double getCelsius() const {
return celsius;
}
double getFahrenheit() const {
return celsius * 9.0/5.0 + 32.0;
}
void setCelsius(double c) {
celsius = c;
}
};
int main() {
const Temperature temp(25.0); // 常量对象
cout << "摄氏温度: " << temp.getCelsius() << "°C" << endl;
cout << "华氏温度: " << temp.getFahrenheit() << "°F" << endl;
// temp.setCelsius(30.0); // 错误:不能通过常量对象调用非const成员函数
return 0;
}
输出结果:
摄氏温度: 25°C
华氏温度: 77°F
常量对象只能调用const成员函数。
类成员的真实应用场景
让我们看一个更复杂的例子,展示类成员在实际应用中的使用:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Book {
private:
string title;
string author;
string isbn;
double price;
int quantity;
public:
// 构造函数
Book(string t, string a, string i, double p, int q)
: title(t), author(a), isbn(i), price(p), quantity(q) {}
// 成员函数
string getTitle() const { return title; }
string getAuthor() const { return author; }
string getISBN() const { return isbn; }
double getPrice() const { return price; }
int getQuantity() const { return quantity; }
void setPrice(double p) { price = p; }
void addStock(int q) {
if (q > 0) quantity += q;
}
bool sellCopies(int q) {
if (q <= quantity) {
quantity -= q;
return true;
}
return false;
}
double getTotalValue() const {
return price * quantity;
}
void display() const {
cout << "书名: " << title << endl;
cout << "作者: " << author << endl;
cout << "ISBN: " << isbn << endl;
cout << "单价: " << price << endl;
cout << "库存: " << quantity << endl;
cout << "库存总值: " << getTotalValue() << endl;
}
};
class Bookstore {
private:
string name;
vector<Book> inventory;
static int totalBooksSold; // 静态成员跟踪所有书店销售的总图书数
public:
Bookstore(string n) : name(n) {}
void addBook(const Book& book) {
inventory.push_back(book);
}
bool sellBook(string isbn, int quantity) {
for (size_t i = 0; i < inventory.size(); i++) {
if (inventory[i].getISBN() == isbn) {
if (inventory[i].sellCopies(quantity)) {
totalBooksSold += quantity;
return true;
}
return false;
}
}
return false;
}
void displayInventory() const {
cout << "=== " << name << " 库存 ===" << endl;
for (size_t i = 0; i < inventory.size(); i++) {
inventory[i].display();
cout << "-------------------" << endl;
}
}
static int getTotalBooksSold() {
return totalBooksSold;
}
};
int Bookstore::totalBooksSold = 0;
int main() {
// 创建一家书店
Bookstore myBookstore("学林书店");
// 添加图书到库存
Book book1("C++ Primer", "Stanley Lippman", "978-0321714114", 45.99, 10);
Book book2("Effective Modern C++", "Scott Meyers", "978-1491903995", 39.99, 5);
myBookstore.addBook(book1);
myBookstore.addBook(book2);
// 显示初始库存
myBookstore.displayInventory();
// 销售图书
cout << "\n销售3本C++ Primer..." << endl;
if (myBookstore.sellBook("978-0321714114", 3)) {
cout << "销售成功!" << endl;
} else {
cout << "销售失败,库存不足!" << endl;
}
// 显示更新后的库存
cout << "\n更新后的库存:" << endl;
myBookstore.displayInventory();
// 显示销售统计
cout << "\n总销售图书数: " << Bookstore::getTotalBooksSold() << endl;
return 0;
}
这个例子展示了一个简单的书店管理系统,其中:
Book
类包含书籍的属性和操作Bookstore
类管理书籍库存- 使用静态成员跟踪所有书店的销售总量
- 演示了const成员函数的使用
总结
类成员是C++面向对象编程的核心概念。在本文中,我们学习了:
- 数据成员和成员函数的基本概念
- 访问控制和访问修饰符(public、private、protected)
- 在类内和类外定义成员函数
- 构造函数和析构函数
- 静态成员(数据和函数)
- const成员函数
- 类成员在实际应用中的使用
正确理解和使用类成员是编写高质量、可维护C++代码的基础。随着你对C++编程的深入学习,你会发现更多使用类成员的高级技巧。
练习
-
创建一个
Point
类,表示2D平面上的点:- 添加私有数据成员
x
和y
- 提供构造函数、getter和setter方法
- 添加计算到另一个点距离的方法
- 添加私有数据成员
-
扩展
Circle
类:- 添加中心点(使用
Point
类)和半径 - 提供计算周长和面积的方法
- 添加一个方法判断一个点是否在圆内
- 添加中心点(使用
-
创建一个
Counter
类:- 使用静态成员记录创建了多少个Counter对象
- 为每个对象提供一个唯一ID
- 添加一个静态方法返回创建的对象总数
通过这些练习,你将能够更好地理解和应用C++中的类成员概念。