面向对象速成
一、class 就是带权限控制的 struct
- struct 默认内容权限为 public(公有),谁都能用
- class 默认内容权限为 private(私有),只有自己能用,其他人只能用 public 的内容
class Animal
{
private: // 私有,藏起来的信息
int age;
public: // 公有,大家能用的信息
void setAge(int a)
{
age = a;
}
int getAge()
{
return age;
}
};
Animal a;
a.setAge(3);
cout << a.getAge() << "\n"; // 输出 3
// cout << a.age << "\n"; // 编译错误
二、继承
class Animal
{
public:
string name;
void eat()
{
cout << name << "吃饭\n";
}
};
class Cat : public Animal
{
public:
void say()
{
cout << name << "喵\n";
}
};
Cat d;
d.name = "咪咪";
d.eat(); // 输出:咪咪吃饭
d.say(); // 输出:咪咪喵
- 默认继承(private 继承):父类的 public 和 protected 成员在子类里变成 private,子类内部能用,但外面不能通过子类对象用。父类的 private 成员子类不能用。
- public 继承:父类的 public 和 protected 子类可以用,父类的 private 子类不能用。
多态与虚函数
class Animal
{
public:
string name;
virtual void say()
{
cout << name << "...\n";
}
virtual ~Animal()
};
class Dog : public Animal
{
public:
void say() override
{
cout << name << "汪\n";
}
};
class Cat : public Animal
{
public:
void say() override
{
cout << name << "喵\n";
}
};
Animal *p1 = new Dog();
Animal *p2 = new Cat();
p1->name = "小黑";
p2->name = "咪咪";
p1->say(); // 小黑汪
p2->say(); // 咪咪喵
delete p1;
delete p2;
- 用父类指针或引用才能多态。
- 用父类对象赋值会切片,子类独有部分丢掉,也不会多态。
构造函数与析构函数
- 构造函数:创造的时候调用
- 析构函数:删除的时候调用
class 父类 {
public:
父类() { ... } // 默认构造
父类(参数) { ... } // 带参构造
virtual ~父类() { ... } // 虚析构
};
class 子类 : public 父类 {
public:
子类() : 父类() { ... } // 先调父类默认构造,可以不写 父类(),会自动调用
子类(参数) : 父类(参数) { ... } // 先调父类带参构造
~子类() { ... } // 先子后父
};
例子
class Animal
{
public:
string name;
int age;
// 默认构造
Animal()
{
name = "无名";
age = 0;
cout << "Animal 默认构造\n";
}
// 带参构造
Animal(string n, int a)
{
name = n;
age = a;
cout << "Animal 带参构造 " << name << "\n";
}
// 虚析构
virtual ~Animal()
{
cout << "Animal 析构 " << name << "\n";
}
};
class Dog : public Animal
{
public:
// 子类默认构造:自动先调 Animal()
Dog()
{
cout << "Dog 默认构造\n";
}
// 子类带参构造:用初始化列表调 Animal(n, a)
Dog(string n, int a) : Animal(n, a)
{
cout << "Dog 带参构造 " << name << "\n";
}
// 子类析构:先执行这里,再执行 Animal::~Animal()
~Dog()
{
cout << "Dog 析构 " << name << "\n";
}
};
cout << "--- 造 d1 ---\n";
Dog d1;
cout << "--- 造 d2 ---\n";
Dog d2("小黑", 3);
cout << "--- new 一只狗,用父类指针 ---\n";
Animal *p = new Dog("小花", 2);
cout << "--- delete ---\n";
delete p;
cout << "--- 程序结束,自动销毁 d2、d1 ---";
- 父类如果没写构造函数,编译器会偷偷生成父类的默认构造。
- 父类如果写了带参构造,那就没有默认构造了,子类必须写先调父类的带参构造。
分类: 分享
· 更新时间 2026-9-12 8:20:37