面试题答案
一键面试- 定义类及成员函数
#include <iostream>
#include <cstring>
class MyClass {
private:
char *str;
public:
MyClass() : str(nullptr) {}
~MyClass() {
if (str) {
delete[] str;
}
}
void print1(const char *p) {
// 这里p是const,不能通过p修改其指向内容,但可以修改类成员str
if (str) {
delete[] str;
}
str = new char[strlen(p) + 1];
std::strcpy(str, p);
std::cout << "print1: " << str << std::endl;
}
void print2(char * const p) {
// p是指向const的指针,不能修改p的指向,但可以修改其指向的内容
if (str) {
delete[] str;
}
str = new char[strlen(p) + 1];
std::strcpy(str, p);
std::cout << "print2: " << str << std::endl;
}
};
- 分析编译和运行问题及原因
- 编译问题:
- 在
print1
函数中,p
是const char*
类型,意味着不能通过p
修改其指向的内容。但该函数本身并没有尝试修改p
指向的内容,而是对类成员变量str
进行操作,所以编译不会因为p
的const
属性而报错。 - 在
print2
函数中,p
是char* const
类型,表明p
的指向不能改变,但可以修改p
指向的内容。同样,该函数对p
指向内容没有修改,而是操作类成员str
,所以编译也不会报错。
- 在
- 运行问题:
- 如果在使用类之前没有正确初始化
str
,直接在print1
或print2
中尝试delete[] str
会导致未定义行为,因为str
可能是一个未初始化的指针。所以在使用delete[]
之前需要先检查str
是否为nullptr
。
- 如果在使用类之前没有正确初始化
- 编译问题:
- 正确处理以满足不同需求
- 读取成员变量需求:
- 如果只是读取成员变量
str
,可以定义一个const
成员函数,例如:
- 如果只是读取成员变量
- 读取成员变量需求:
const char* getStr() const {
return str;
}
- **修改成员变量需求**:
- 像上述`print1`和`print2`函数,在修改`str`之前需要先释放其原有内存(如果存在),然后重新分配内存并复制新的内容。
这样可以确保在不同需求下,类的行为是安全且符合预期的。