选择-友元
下列关于 友元 的说法,正确的是
A. 友元关系可继承
B. 友元函数必须是成员函数
C. 友元可访问类的私有成员,但破坏封装需谨慎使用
D. 友元声明只能写在类外
选C
-
A 错:友元关系不能继承
-
B 错:友元函数不一定是成员函数,很多友元函数本来就是类外普通函数
-
C 对:友元可以访问类的私有成员,但会削弱封装性,应谨慎使用
-
D 错:友元声明通常写在类内
选择-运算符重载
下列哪项属于运算符重载限制
A. 不能重载 +
B. 不能改变运算符的优先级与结合性
C. 重载后可把二元运算符变成三元
D. 运算符重载只能写成成员函数
选B
-
A 错:
+可以重载 -
B 对:不能改变运算符的优先级和结合性
-
C 错:不能把二元运算符重载成三元
-
D 错:运算符重载既可以写成成员函数,也可以写成非成员函数(常配合友元)
填空-虚析构
- 若基类指针删除派生类对象,为保证派生类析构被调用,基类析构函数应声明为
virtual 析构函数
填空-常指针
const成员函数中,隐含的this指针类型等价于:
const Point * const 指针指向和指针的值都不可修改
**简答题-**静态联编 vs 动态联编
说明"静态联编 vs 动态联编"的触发条件、典型代码形态与各自优缺点
1. 静态联编
静态联编也叫早绑定 ,在编译期就确定调用哪个函数。
触发条件
-
调用普通函数
-
调用非虚成员函数
-
重载函数的匹配
-
模板实例化后的调用
典型代码形态
cpp
class Base{
public:
void show(){ cout << "Base\n"; }
};
int main(){
Base b;
b.show(); // 编译期确定
}
优点
-
调用效率高
-
编译器容易优化
-
实现简单
缺点
-
灵活性差
-
不能体现运行时多态
2. 动态联编
动态联编也叫晚绑定 ,在运行期根据对象的真实类型决定调用哪个虚函数。
触发条件
必须同时满足:
-
基类中该函数是 virtual
-
通过 基类指针或基类引用
-
实际绑定的是 派生类对象
典型代码形态
cpp
class Base{
public:
virtual void show(){ cout << "Base\n"; }
};
class Derive : public Base{
public:
void show() override { cout << "Derive\n"; }
};
int main(){
Base *p = new Derive;
p->show(); // 运行期决定,输出 Derive
delete p;
}
优点
-
支持运行时多态
-
扩展性强
-
更符合面向对象设计
缺点
-
有一点运行时开销
-
需要虚函数表等机制
-
代码理解难度略高
程序改错-const


程序填空-菱形继承

代码题

cpp
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class Date{
private:
int y, m, d;
public:
Date(int yy = 0, int mm = 0, int dd = 0): y(yy), m(mm), d(dd) {}
void Print(ostream &out) const{
out << y << "-"
<< setw(2) << setfill('0') << m << "-"
<< setw(2) << setfill('0') << d;
}
};
class Person{
private:
string name;
Date birthday; // 子对象
public:
Person(const string &n, const Date &b): name(n), birthday(b) {}
void Print(ostream &out) const{
out << name << " ";
birthday.Print(out);
}
};
void Show(const Person &p){
p.Print(cout);
}
int main(){
string name;
int y, m, d;
cin >> name >> y >> m >> d;
Date birth(y, m, d);
Person p(name, birth);
Show(p);
return 0;
}