面试题答案
一键面试- 潜在差异分析:
- 模板实例化:在C++中,
class
和struct
在模板实例化方面,语法上没有本质区别。编译器会根据模板参数的实际类型(class
或struct
)来实例化模板类。例如,MyTemplate<MyClass>
和MyTemplate<MyStruct>
都会正确实例化模板类MyTemplate
。 - 访问权限传播:
class
类型:默认情况下,class
的成员是private
的。当T
是class
类型时,如果模板类MyTemplate
要访问T
的成员,那么T
的成员需要设置为public
或者MyTemplate
需要成为T
的友元类。struct
类型:默认情况下,struct
的成员是public
的。所以当T
是struct
类型时,模板类MyTemplate
可以直接访问T
的成员,只要这些成员没有被显式声明为private
或protected
。
- 模板实例化:在C++中,
- 代码示例:
// 定义一个class类型
class MyClass {
private:
int data;
public:
MyClass(int d) : data(d) {}
int getData() const {
return data;
}
};
// 定义一个struct类型
struct MyStruct {
int data;
MyStruct(int d) : data(d) {}
};
// 模板类
template <typename T>
class MyTemplate {
public:
void printData(const T& obj) {
// 对于MyClass,需要通过public接口访问data
// 对于MyStruct,可以直接访问data
// 这里使用条件编译来处理不同情况
#ifdef USE_CLASS
std::cout << "Data from MyClass: " << obj.getData() << std::endl;
#else
std::cout << "Data from MyStruct: " << obj.data << std::endl;
#endif
}
};
int main() {
MyClass myClass(10);
MyStruct myStruct(20);
MyTemplate<MyClass> classTemplate;
MyTemplate<MyStruct> structTemplate;
classTemplate.printData(myClass);
structTemplate.printData(myStruct);
return 0;
}
- 应对问题:
- 使用条件编译:如上述代码中,通过条件编译(
#ifdef USE_CLASS
)可以在模板类中根据T
是class
还是struct
类型来调整对成员的访问方式。 - 使用 traits 技术:可以定义类型 traits 来检测
T
是class
还是struct
,然后在模板类中根据 traits 的结果来决定访问成员的方式。例如:
- 使用条件编译:如上述代码中,通过条件编译(
template <typename T>
struct IsClass {
static const bool value = false;
};
template <typename T>
struct IsClass<T*> {
static const bool value = false;
};
template <typename T>
struct IsClass<const T> {
static const bool value = IsClass<T>::value;
};
template <typename T>
struct IsClass<volatile T> {
static const bool value = IsClass<T>::value;
};
template <typename T>
struct IsClass<const volatile T> {
static const bool value = IsClass<T>::value;
};
template <class T>
struct IsClass<T> {
static const bool value = true;
};
template <typename T>
class MyTemplate {
public:
void printData(const T& obj) {
if constexpr (IsClass<T>::value) {
std::cout << "Data from MyClass: " << obj.getData() << std::endl;
} else {
std::cout << "Data from MyStruct: " << obj.data << std::endl;
}
}
};
这种方式更加灵活,不需要手动修改宏定义,编译器会根据类型自动选择合适的访问方式。