类与对象
类的介绍
类是用户定义的数据类型,封装数据和函数。它们是 C++ 面向对象编程的基础。
简单类示例
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
double gpa;
public:
// Constructor
Student(const string& n, int a, double g) {
name = n;
age = a;
gpa = g;
}
// Getter methods
string getName() const { return name; }
int getAge() const { return age; }
double getGPA() const { return gpa; }
// Method to display information
void displayInfo() const {
cout << "Name: " << name << ", Age: " << age << ", GPA: " << gpa << endl;
}
};
int main() {
Student student1("Alice", 20, 3.8);
student1.displayInfo();
return 0;
}封装
将数据和方法绑定在一起,隐藏内部细节
抽象
为复杂功能提供简化的接口
继承
基于现有类创建新类
多态
使用一个接口处理不同的底层形式
基本类定义
以下是如何定义一个简单的类:
简单类示例
#include <iostream>
#include <string>
using namespace std;
class Student {
private: // Private members (data hiding)
string name;
int age;
double gpa;
public: // Public members (interface)
// Constructor
Student(const string& n, int a, double g) {
name = n;
age = a;
gpa = g;
}
// Getter methods
string getName() const {
return name;
}
int getAge() const {
return age;
}
double getGPA() const {
return gpa;
}
// Setter methods
void setGPA(double newGPA) {
if (newGPA >= 0.0 && newGPA <= 4.0) {
gpa = newGPA;
}
}
// Method to display information
void displayInfo() const {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "GPA: " << gpa << endl;
}
};
int main() {
// Create objects
Student student1("Alice", 20, 3.8);
Student student2("Bob", 19, 3.5);
// Use methods
student1.displayInfo();
cout << "---" << endl;
student2.displayInfo();
// Modify using setter
student1.setGPA(3.9);
cout << "Updated GPA: " << student1.getGPA() << endl;
return 0;
}构造函数和析构函数
构造函数初始化对象,而析构函数清理资源:
构造函数和析构函数
#include <iostream>
#include <string>
using namespace std;
class Rectangle {
private:
double width;
double height;
public:
// Default constructor
Rectangle() {
width = 0.0;
height = 0.0;
cout << "Default constructor called" << endl;
}
// Parameterized constructor
Rectangle(double w, double h) {
width = w;
height = h;
cout << "Parameterized constructor called" << endl;
}
// Copy constructor
Rectangle(const Rectangle& other) {
width = other.width;
height = other.height;
cout << "Copy constructor called" << endl;
}
// Destructor
~Rectangle() {
cout << "Destructor called for rectangle "
<< width << "x" << height << endl;
}
// Methods
double getArea() const {
return width * height;
}
double getPerimeter() const {
return 2 * (width + height);
}
void display() const {
cout << "Rectangle: " << width << " x " << height
<< " (Area: " << getArea() << ")" << endl;
}
};
int main() {
cout << "Creating rectangles:" << endl;
Rectangle rect1; // Default constructor
Rectangle rect2(5.0, 3.0); // Parameterized constructor
Rectangle rect3 = rect2; // Copy constructor
cout << "\nRectangle information:" << endl;
rect1.display();
rect2.display();
rect3.display();
cout << "\nExiting main (destructors will be called):" << endl;
return 0;
}访问修饰符
C++ 为类成员提供三种访问级别:
| 访问级别 | 同一类 | 派生类 | 类外部 |
|---|---|---|---|
private | ✅ | ❌ | ❌ |
protected | ✅ | ✅ | ❌ |
public | ✅ | ✅ | ✅ |
访问修饰符示例
#include <iostream>
using namespace std;
class BankAccount {
private:
double balance; // Only accessible within the class
string accountNumber; // Hidden from outside access
protected:
int accountType; // Accessible in derived classes
public:
string ownerName; // Accessible everywhere
// Constructor
BankAccount(const string& owner, const string& accNum, double initialBalance) {
ownerName = owner;
accountNumber = accNum;
balance = initialBalance;
accountType = 1; // Default type
}
// Public methods to access private data
double getBalance() const {
return balance;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
cout << "Deposited $" << amount << endl;
}
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
cout << "Withdrew $" << amount << endl;
return true;
}
cout << "Insufficient funds or invalid amount" << endl;
return false;
}
void displayInfo() const {
cout << "Owner: " << ownerName << endl;
cout << "Balance: $" << balance << endl;
// cout << "Account: " << accountNumber << endl; // Can access private here
}
};
int main() {
BankAccount account("John Doe", "123456789", 1000.0);
// Can access public members
cout << "Account holder: " << account.ownerName << endl;
// Can use public methods
account.deposit(500.0);
account.withdraw(200.0);
account.displayInfo();
// Cannot access private members directly
// cout << account.balance; // Error!
// cout << account.accountNumber; // Error!
return 0;
}静态成员
静态成员属于类而不是单个对象:
静态成员示例
#include <iostream>
using namespace std;
class Counter {
private:
int value;
static int totalObjects; // Static data member
public:
// Constructor
Counter(int val = 0) : value(val) {
totalObjects++; // Increment when object is created
}
// Destructor
~Counter() {
totalObjects--; // Decrement when object is destroyed
}
// Regular member function
int getValue() const {
return value;
}
void setValue(int val) {
value = val;
}
// Static member function
static int getTotalObjects() {
return totalObjects; // Can only access static members
// return value; // Error! Cannot access non-static members
}
// Static member function to display count
static void displayCount() {
cout << "Total Counter objects: " << totalObjects << endl;
}
};
// Definition of static member (required outside class)
int Counter::totalObjects = 0;
int main() {
cout << "Initial count: ";
Counter::displayCount(); // Call static function using class name
Counter c1(10);
Counter c2(20);
cout << "After creating 2 objects: ";
Counter::displayCount();
{
Counter c3(30);
cout << "After creating 3rd object: ";
Counter::displayCount();
} // c3 goes out of scope and is destroyed
cout << "After c3 is destroyed: ";
Counter::displayCount();
// Can also call static function through object
cout << "Total objects (via object): " << c1.getTotalObjects() << endl;
return 0;
}友元函数
友元函数可以访问类的私有和保护成员:
友元函数示例
#include <iostream>
#include <cmath>
using namespace std;
class Point {
private:
double x, y;
public:
Point(double xVal = 0, double yVal = 0) : x(xVal), y(yVal) {}
void display() const {
cout << "(" << x << ", " << y << ")";
}
// Declare friend function
friend double distance(const Point& p1, const Point& p2);
friend Point midpoint(const Point& p1, const Point& p2);
// Friend class declaration (if needed)
friend class Line;
};
// Friend function definition
double distance(const Point& p1, const Point& p2) {
// Can access private members x and y directly
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
Point midpoint(const Point& p1, const Point& p2) {
// Can access private members directly
return Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
}
// Example of friend class
class Line {
private:
Point start, end;
public:
Line(const Point& s, const Point& e) : start(s), end(e) {}
void displayLine() const {
cout << "Line from ";
start.display();
cout << " to ";
end.display();
cout << endl;
// Can access private members of Point because Line is a friend
cout << "Start coordinates: x=" << start.x << ", y=" << start.y << endl;
cout << "End coordinates: x=" << end.x << ", y=" << end.y << endl;
}
};
int main() {
Point p1(3, 4);
Point p2(7, 1);
cout << "Point 1: ";
p1.display();
cout << endl;
cout << "Point 2: ";
p2.display();
cout << endl;
cout << "Distance: " << distance(p1, p2) << endl;
Point mid = midpoint(p1, p2);
cout << "Midpoint: ";
mid.display();
cout << endl;
Line line(p1, p2);
line.displayLine();
return 0;
}类的最佳实践
封装原则
保持数据成员私有,提供公共方法进行访问
构造函数初始化
使用初始化列表以获得更好的性能和常量成员
常量正确性
如果方法不修改对象状态,将其标记为 const
RAII 原则
资源获取即初始化 - 在构造函数/析构函数中管理资源
单一职责
每个类应该只有一个改变的理由
有意义的命名
为类、方法和成员使用描述性名称