9

struct 关键字在 C++ 中与C语言不同,C++中struct和class有什么区别?它们很像,C++为...

 3 years ago
source link: https://blog.popkx.com/struct-in-c-is-different-from-c-it-looks-more-like-class/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

struct 关键字在 C++ 中与C语言不同,C++中struct和class有什么区别?它们很像,C++为什么不删除struct?

发表于 2020-05-09 08:05:00   |   已被 访问: 276 次   |   分类于:   C++   |   暂无评论

我有相当长的一段时间(数月)没有更新文章了。

并不是我放弃了写技术文章,而是因为这段时间,我把精力主要放在了图像智能算法的学习上了。去年12月时,我对图像智能算法还懵懵懂懂,做着 Linux 嵌入式应用程序开发,现在我已经正式入职到算法公司了,收入翻了一番,哈哈,不过累了好多。废话就到这里,我的转行辛酸史,以后再详谈。

坦诚的说,就编程语言而言,因为一直在做 Linux 嵌入式程序开发的缘故,我对C语言更加了解一点,读者应该能够发现,我之前的大部分文章都是关于C语言的。不过现在做算法,C++更加适合。C++和C语言虽然很像,但是在细节上还是有所区别的。今天阅读前辈同事的代码时,注意到了 struct 关键字,这个关键字在C++中做了不少扩展。本文将尝试做下总结。

C语言与C++中的struct

struct关键字是C语言中非常重要的关键字,在实际的C语言程序开发中,struct 不仅可以用于封装各种复杂的数据结构,还能够实现一些开发技巧——比如辅助数组赋值、模拟类等等,这些我之前的文章都讨论过。C++不仅保留了C语言中 struct 的功能,还做了不少扩展,具体的可以通过下面这个表说明:

.C语言C++成员函数不能可以静态成员不能可以访问控制属性等价publicpublic/private/protected可以继承否是

请看下面这段C++代码示例,我们首先使用 struct 定义了 S1,接着又定义了 S2,S2 继承了 S1,因此我们可以在 test2 中使用 S1 中定义的成员 a、b。同时也可以看出,C++中的 struct 还可以定义成员函数,包括构造函数和析构函数。

#include <iostream>

using namespace std;

struct S1 {
    int    a;
    int    b;

    S1() {
        a = 1;
        b = 2;
    }

    void print_mem() {
        cout << "a = "<< a << ", b = "<<b <<endl;
    }
};

struct S2: S1 {
    int        c;
    ~S2() {
        cout << "S2 exit, c = " << c << endl;
        cout << "a = "<< a << ", b = "<<b <<endl;
    }
};

int main()
{
    S1 test1;
    test1.print_mem();

    S2 test2;
    test2.a = 3;
    test2.b = 4;
    test2.c = 5;

    return 0;
}

编译并执行上述C++代码,不出意外地得到如下输出:

$ g++ t1.cpp 
$ ./a.out 
a = 1, b = 2
S2 exit, c = 5
a = 3, b = 4

C++ 中的 struct 和 class 关键字

从上面的例子不难看出,C++中的 struct 除了像C语言那样可以定义数据结构外,还可以像 class 关键字那样定义成员函数。不过,二者是有区别的。

成员的默认访问控制属性

首先,struct 默认的访问控制属性是 public,而 class 默认的访问控制属性是 private,这一点可以通过下面这段C++代码示例看出:

struct A {
    int a;
};
class B {
    int b;
};

A ta;
ta.a = 1; // 没有问题

B tb;
tb.b = 2; // 编译报错

继承的默认访问控制属性

类似的,在继承的过程中,struct 和 class 关键字的默认访问控制属性也是有所区别的:struct 默认 public,class 默认 private,例如下面这段C++ 代码:

struct A {
    int a;
};
struct B: A {
    int b;
};

B tb;
tb.a = 1; // 正常

这是没有问题的,对象 tb 可以访问由 A 继承而来的成员 a。但是如果将 B 的 struct 改为 class,也即:

struct A {
    int a;
};
class B: A {
    int b;
};

B tb;
tb.a = 1; // 编译报错

此时编译就会报错,提示“‘int A::a’ is inaccessible”,因为 class 的默认继承属性为 private。现在我们将 A 的 struct 修改为 class,B 的 class 再改回 struct,会发现,对象 tb 依然能够正常访问成员 a:

class A {
public:
    int a;
};
struct B: A {
    int b;
};

B tb;
tb.a = 1; // 正常

应注意,这里的讨论重点是继承的默认访问控制属性,因此我们将 A 中的 a 定义为 public 的。

可以看出,当 class 和 struct 混合使用时,默认的访问控制属性由子类决定,而不是由基类决定。不过,依赖默认属性不是特别清晰的写法,在实际的C++程序开发中,更推荐的做法是指明继承的方式:

class B: private A {
    ...
};
class B: public A {
    ...
};

相较于C语言,C++还能够定义模板函数,请看下面这段代码示例:

template<typename T>                                                                                             void fun(T num) {
     cout << "num = " << num << endl;
} 
fun(1); // num = 1
fun(1.01); // num = 1.01

在一些开源工程中,我还发现过有使用 class 定义模板函数的,也即使用class替换typename关键字:

template<class T>                                                                                             void fun(T num) {
     cout << "num = " << num << endl;
} 

这种定义方式和上面使用typename的定义方式完全相同,但是 struct 就不能用于定义模板函数,如果读者尝试了,应该会得到编译报错的结果。

本文先是讨论了 struct 关键字在C语言和C++中的不同,不难发现,C++对 struct 关键字是做了不少扩充的,这些扩充让 struct 看起来更像是 class 关键字。事实上,我认为就单纯C++来说,class 关键字是完全可以取代 struct 的,C++ 仍然保留着 struct 关键字,其中一个重要原因就是兼容C语言。既然保留了 struct 关键字,总不能让它完全等价于 class,因此二者在一些细节上有区别,这些轻微的区别往往能够针对不同的需求提供不同的方便:struct 更适合封装数据结构,class 则更适合封装对象。

阅读更多:   C++


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK