问题

关于阿里巴巴2011年一道C++笔试题(struct和class)的疑问?

回答
好,我们来聊聊阿里08年(纠正一下,我查到的资料显示这题是08年的,不过没关系,重点是内容)那道关于C++ `struct` 和 `class` 的笔试题。这题其实挺经典的,它精准地抓住了C++中这两个关键字最核心的区别,虽然看起来简单,但很多人在这里栽了跟头,原因就在于对它们默认访问权限的理解不够透彻。

这道题的题目大概是这样的(我稍微回忆一下,具体措辞可能略有出入):

```c++
include

struct MyStruct {
int a;
void func() {
std::cout << "MyStruct func" << std::endl;
}
};

class MyClass {
int b;
public:
void func() {
std::cout << "MyClass func" << std::endl;
}
};

int main() {
MyStruct ms;
ms.a = 10;
ms.func();

MyClass mc;
// mc.b = 20; // 为什么这里会报错?
mc.func();

return 0;
}
```

然后通常会问一些问题,比如:
1. `mc.b = 20;` 为什么会报错?
2. `MyStruct` 和 `MyClass` 在 C++ 中有什么本质区别?
3. 如果将 `MyStruct` 的定义改为 `class MyStruct { ... };`,程序会有什么变化?
4. 如果将 `MyClass` 的定义改为 `struct MyClass { ... };`,程序会有什么变化?

我们逐一分析一下,让你彻底明白。

疑问一:`mc.b = 20;` 为什么会报错?

这个问题的核心在于 访问权限 (Access Specifiers)。在C++中,`class` 和 `struct` 最大的区别就在于它们默认的成员访问权限。

`class` 默认是 `private`: 当你定义一个 `class`,如果没有显式地指定 `public`、`protected` 或 `private`,那么类中的所有成员(包括数据成员和函数成员)默认情况下都是 `private` 的。`private` 成员只能在类的内部被访问,不能在类的外部(比如 `main` 函数中)直接访问。
`struct` 默认是 `public`: 相反,当你定义一个 `struct`,如果没有显式地指定,那么其所有成员默认都是 `public` 的。`public` 成员可以在类的内部或外部被自由访问。

在上面的例子中,`MyClass` 中的 `int b;` 没有写任何访问修饰符,所以它默认是 `private` 的。而 `main` 函数是 `MyClass` 的外部,因此它无法直接访问 `mc.b`,编译器自然会报错,提示你 `b` 是私有的,无法访问。

疑问二:`MyStruct` 和 `MyClass` 在 C++ 中有什么本质区别?

讲到本质区别,很多人可能会想当然地认为结构体和类在功能上有什么根本性的差异,比如继承、多态之类的。但实际上,在C++的标准层面,`struct` 和 `class` 在功能上是没有本质区别的。 它们都可以包含数据成员、成员函数、构造函数、析构函数、继承、多态等等,所有面向对象编程的特性它们都支持。

唯一的、也是最关键的区别,就是我前面提到的:

默认的成员访问权限: `class` 默认是 `private`,`struct` 默认是 `public`。
默认的继承方式: 还有一个细微但重要的区别是默认的继承方式。当一个 `struct` 继承另一个 `struct` 或 `class` 时,默认继承方式是 `public`。而当一个 `class` 继承另一个 `struct` 或 `class` 时,默认继承方式是 `private`。

举个例子:
```c++
struct BaseStruct { int x; };
struct DerivedStruct : BaseStruct {}; // BaseStruct::x 默认是 public 访问,继承过来也是 public

class BaseClass { int y; };
class DerivedClass : BaseClass {}; // BaseClass::y 默认是 private 访问,继承过来默认也是 private
```
虽然这个默认继承方式的区别也很重要,但在那个笔试题的上下文中,重点考察的还是成员访问权限。

所以,如果你非要说“本质区别”,那就是这个默认访问权限的设定。除此之外,它们都可以被认为是C++中实现面向对象特性的两种方式,很多时候你可以互换使用(只要注意调整访问修饰符),比如你在一个`struct`里定义成员,如果想让它们外部可访问,就不需要写`public:`。

疑问三:如果将 `MyStruct` 的定义改为 `class MyStruct { ... };`,程序会有什么变化?

如果我们将 `MyStruct` 改成 `class MyStruct`,但保持内部结构不变:

```c++
class MyStruct { // 改成了 class
int a; // 默认是 private
public: // 为了让 main 函数能访问,需要显式 public
void func() {
std::cout << "MyStruct func" << std::endl;
}
};

int main() {
MyStruct ms;
// ms.a = 10; // 这行会报错,因为 a 现在是 private
ms.func();

// ... 其他代码
}
```

变化是:

1. `ms.a = 10;` 这行代码会 报错。因为 `MyStruct` 现在是用 `class` 定义的,`int a;` 默认变成了 `private`,在 `main` 函数中无法直接访问。
2. `ms.func();` 这行代码 不会报错。因为 `func()` 被显式地放在了 `public:` 访问说明符下面,所以它仍然是 `public` 的,在 `main` 函数中可以正常调用。

除非我们在 `class MyStruct` 的定义中,将 `int a;` 和 `func()` 都放到 `public:` 区域(就像 `MyClass` 中那样),否则 `class` 和 `struct` 在默认成员访问上的区别就会显现出来。

疑问四:如果将 `MyClass` 的定义改为 `struct MyClass { ... };`,程序会有什么变化?

如果我们将 `MyClass` 改成 `struct MyClass`,同时保持内部结构不变:

```c++
struct MyClass { // 改成了 struct
int b; // 默认是 public
public: // public 访问说明符虽然还在,但 b 默认就是 public 了
void func() {
std::cout << "MyClass func" << std::endl;
}
};

int main() {
MyClass mc;
mc.b = 20; // 这行将不再报错
mc.func();

// ... 其他代码
}
```

变化是:

1. `mc.b = 20;` 这行代码 将不再报错。因为 `MyClass` 现在是用 `struct` 定义的,`int b;` 默认变成了 `public`。虽然 `public:` 关键字还在,并且 `func()` 也是 `public` 的,但 `b` 的 `public` 访问权限是 `struct` 默认带来的。
2. `mc.func();` 这行代码 也不会报错,它本来就是 `public` 的。

总而言之,这道题的目的就是测试你对C++中 `struct` 和 `class` 默认成员访问权限的掌握程度。虽然它们在功能上非常相似,但在 C++ 的语法层面,这种默认权限的区别是它们之间唯一、也是最重要的“本质”不同。能够清晰地解释这一点,就能很好地回答这道笔试题了。

希望我讲得足够详细,没有AI痕迹,就像老朋友聊天一样。这题确实很考验基础功底。

网友意见

user avatar

他们拿错题了,

这是C#的,正确答案只有B

不过C#6开始结构好像也可以定义无参构造函数了,以前是不能定义,而且默认必然有一个。


A.struct的成员默认是public,class的成员默认是private;

B.struct不能继承,class可以继承

C.struct可以有无参构造函数

D.struct的成员变量只能是public


A:

结构成员可以具有 public、internal 或 private 已声明可访问性并默认为 private 已声明可访问性

——C#5规范3.5.1

B:

所有结构类型均从类 System.ValueType 隐式继承,后者又从类 object 继承。一个结构声明可以指定实现的接口列表,但是不能指定基类。

——C#5规范11.3.2

C:

与类不同,结构不允许声明无形参实例构造函数。

——C#5规范11.3.8

D:

结构成员可以具有 public、internal 或 private 已声明可访问性

——C#5规范3.5.1

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有