【C/C++基础语法】

1. C++结构体和C结构体的区别

C++中的结构体在某些方面与类类似,而C中的结构体更像是一组相关的变量的集合。

具体来说包括以下六点:

  • 访问权限
  • 成员函数
  • 构造函数和析构函数
  • 继承
  • 初始化
  • 名称空间.

1. 访问权限

C++中的结构体支持三种访问权限,而C中的结构体内部成员变量只能是private

  • public表示该成员可以被该类的任何对象、任何函数和其他类中的成员函数访问;
  • private表示该成员只能被该类的成员函数访问,其他函数和其他类都无法访问;
  • protected表示该成员可以被该类的成员函数和该类的派生类的成员函数访问,其他函数和其他类都无法访问。

2. 成员函数

C++中的结构体可以包含成员函数,而C中的结构体只能包含成员变量。

3. 构造函数和析构函数

C++中的结构体可以有构造函数和析构函数,而C中的结构体没有。

构造函数和析构函数:

  • 构造函数
  1. 构造函数与类同名,
  2. 没有返回值,可以有参数,可以被重载。
  3. 每个对象在创建时都会自动调用构造函数,确保对象的成员变量被正确初始化。
  4. 如果没有定义构造函数,C++会自动生成一个默认构造函数,但该构造函数不会进行任何初始化操作。
  • 析构函数:
  1. 析构函数与类同名,在名称前加上一个波浪号~
  2. 没有返回值,没有参数,不可被重载。
  3. 在对象被销毁时自动调用,释放对象占用的资源。
  4. 如果没有自定义析构函数,编译器会提供默认的析构函数。默认的析构函数不执行任何操纵。

4. 继承:

C++中的结构体可以继承自其他结构体或类,而C中的结构体不支持继承。

5. 成员初始化:

C++中的结构体可以使用成员初始化列表初始化其成员变量,而C中的结构体只能在定义后逐个成员变量进行初始化。

6. 名称空间:

C++中的结构体可以定义在名称空间中,而C中的结构体不能。

  • 在 C++ 中,可以使用 namespace 关键字来定义一个名称空间。并且支持嵌套,即在一个名称空间中定义一个名称空间。
  • C中,没有名称空间的概念。
  • 下面是定义名称空间的语法:
#include <iostream>
using namespace std;

// 定义名称空间 MySpace
namespace MySpace {
   int my_variable = 10;

   void my_function() {
      cout << "Hello from MySpace!" << endl;
   }
}

int main() {
   // 访问名称空间 MySpace 中的变量和函数
   cout << MySpace::my_variable << endl;
   MySpace::my_function();
   return 0;
}

  • 嵌套名称空间
namespace OuterSpace {
   int outer_variable = 10;

   namespace InnerSpace {
      int inner_variable = 20;
   }
}

cout << OuterSpace::outer_variable << endl;
cout << OuterSpace::InnerSpace::inner_variable << endl;

举个结构体包含成员函数、析构函数和构造函数的例子,以及继承的使用。

#include <iostream>

struct MyStruct {
    int x;
    MyStruct(int a) : x(a) { // 构造函数
        std::cout << "MyStruct constructed with " << a << std::endl;
    }
    ~MyStruct() { // 析构函数
        std::cout << "MyStruct destructed with " << x << std::endl;
    }
    void print() { // 成员函数
        std::cout << "x = " << x << std::endl;
    }
};

struct MyDerivedStruct : public MyStruct {
    std::string name;
    MyDerivedStruct(int a, const std::string& s) : MyStruct(a), name(s) { // 构造函数
        std::cout << "MyDerivedStruct constructed with " << a << " and " << s << std::endl;
    }
    void setName(const std::string& s) { // 成员函数
        name = s;
    }
};

int main() {
    MyDerivedStruct obj(42, "Alice");
    obj.print();
    obj.setName("Bob");
    std::cout << "MyDerivedStruct's name is " << obj.name << std::endl;
    return 0;//结构体obj被释放后会自动调用析构函数,所以最后打印MyStruct destructed with 42
}
MyStruct constructed with 42
MyDerivedStruct constructed with 42 and Alice
x = 42
MyDerivedStruct's name is Bob
MyStruct destructed with 42

最后顺便说说C++中,结构体和类的区别:

在C++中,结构体和类的区别是很小的,甚至可以说只有默认访问控制不同.

  • 默认访问权限:对于类而言,成员默认的访问权限是private;而对于结构体而言,成员默认的访问权限是public
  • 继承:类支持publicprotectedprivate三种继承方式,而结构体只支持public继承方式。
  • 使用场景:类通常用于面向对象的程序设计,它更加注重数据和操作的封装和抽象,用于定义复杂的对象类型;而结构体通常用于简单的数据类型的定义和组织,主要用于存储数据。

2. 定义一个类,默认会生成哪些函数?

默认构造函数(Default constructor): 如果没有显式定义,编译器会自动生成一个默认构造函数,用于创建对象。
拷贝构造函数(Copy constructor):用于将一个已经存在的对象拷贝到新的对象中,如对象作为函数参数传递、返回对象时会被调用。
移动构造函数(Move constructor):C++11新增的功能,用于将一个右值对象(rvalue)的资源转移给另一个对象,减少资源拷贝的开销。
析构函数(Destructor):对象销毁时被调用,用于释放对象占用的资源,如内存、文件句柄等。
拷贝赋值函数(Copy assignment operator):用于将一个已经存在的对象赋值给另一个对象。
移动赋值函数(Move assignment operator):C++11新增的功能,用于将一个右值对象的资源转移给另一个对象。
等于运算符重载函数(Equality operator overload):用于比较两个对象是否相等。
输出流运算符重载函数(Output stream operator overload):用于将对象输出到输出流中,如std::cout。
输入流运算符重载函数(Input stream operator overload):用于从输入流中读取对象,如std::cin。

需要注意的是,如果定义了拷贝构造函数、拷贝赋值函数或析构函数,则需要同时定义移动构造函数和移动赋值函数,否则编译器会生成默认版本的移动函数,这些函数可能会导致程序性能下降。此外,如果定义了等于运算符重载函数,则建议同时定义不等于运算符重载函数。

#include <iostream>
#include <string>

class MyClass {
public:
    // 默认构造函数
    MyClass() : num_(0), str_("") {
        std::cout << "Default constructor called" << std::endl;
    }

    // 拷贝构造函数
    MyClass(const MyClass& other) : num_(other.num_), str_(other.str_) {
        std::cout << "Copy constructor called" << std::endl;
    }

    // 拷贝赋值函数
    MyClass& operator=(const MyClass& other) {
        std::cout << "Copy assignment operator called" << std::endl;
        if (this != &other) {
            num_ = other.num_;
            str_ = other.str_;
        }
        return *this;
    }

    // 移动构造函数
    MyClass(MyClass&& other) noexcept : num_(std::move(other.num_)), str_(std::move(other.str_)) {
        std::cout << "Move constructor called" << std::endl;
    }

    // 移动赋值函数
    //&&是右值引用的声明符号,noexcept是指示符,表示该函数不会抛出异常。
    MyClass& operator=(MyClass&& other) noexcept {
        std::cout << "Move assignment operator called" << std::endl;
        if (this != &other) {
            num_ = std::move(other.num_);
            str_ = std::move(other.str_);
            
        }
        return *this;
    }

    // 析构函数
    ~MyClass() {
        std::cout << "Destructor called" << std::endl;
    }

    // ==运算符重载函数
    bool operator==(const MyClass& other) const {
        return num_ == other.num_ && str_ == other.str_;
    }

    // <<运算符重载函数
    //输入运算符重载函数的第一个参数是标准输入流对象std::istream&,因此它无法访问类的私有成员。
    //为了让输入运算符重载函数能够访问私有成员,需要将其声明为类的友元函数。声明为友元函数后,输入运算符重载函数就可以访问类的私有成员了。
    friend std::ostream& operator<<(std::ostream& os, const MyClass& obj) {
        os << "Num: " << obj.num_ << ", Str: " << obj.str_;
        return os;
    }

    // >>输入运算符重载函数
    friend std::istream& operator>>(std::istream& is, MyClass& obj) {
        is >> obj.num_ >> obj.str_;
        return is;
    }

private:
    int num_;
    std::string str_;
};

int main() {
    // Default constructor
    MyClass obj1;

    // Copy constructor
    MyClass obj2(obj1);

    // Copy assignment operator
    MyClass obj3 = obj2;

    // Move constructor
    MyClass obj4(std::move(obj3));

    // Move assignment operator
    MyClass obj5;
    obj5 = std::move(obj4);

    // Operator overloading for ==
    MyClass obj6(10, "hello");
    MyClass obj7(10, "world");
    if (obj6 == obj7) {
        std::cout << "Equal" << std::endl;
    }
    else {
        std::cout << "Not equal" << std::endl;
    }

    // Output stream operator overloading
    MyClass obj8(5, "hi");
    std::cout << obj8 << std::endl;

    // Input stream operator overloading
    MyClass obj9;
    std::cin >> obj9;
    std::cout << obj9 << std::endl;

    return 0;
}
Default constructor called
Copy constructor called
Copy assignment operator called
Move constructor called
Move assignment operator called
Not equal
Num: 5, Str: hi
10 world
Num: 10, Str: world
Destructor called
Destructor called
Destructor called
Destructor called
Destructor called

3. 简述一下C++语言的特点有哪些?

1 .面向对象:C++是一种面向对象的编程语言,支持封装、继承和多态等面向对象特性。
2. 高效性:C++ 是一种编译型语言,能够直接转化为机器语言,因此具有高效性和高性能。同时,C++ 还支持底层操作,如指针和内存管理,可以直接访问计算机硬件资源。
3. 可移植性:C++程序可以在不同的操作系统和计算机平台上编译和运行。
4. 灵活性:C++提供了丰富的语法结构和数据类型,程序员可以根据需要自由地定义类、函数和变量等。
5. 扩展性:C++ 支持面向对象编程和模板编程,可以定义自己的类和数据类型,也可以编写自己的模板库,提高程序的可扩展性。
6. 可靠性:C++具有类型检查和内存安全等特性,可以有效地避免程序中的一些错误。增加了const参量、引用、四类cast转换、智能指针、try-catch等。
7. 可复用性高:C++的语法比较复杂,但是它提供了许多高级编程工具,例如类库和模板,可以提高程序员的开发效率。C++ 标准库提供了丰富的 API,包括容器、算法、字符串处理、正则表达式、数学计算、日期时间等等,使得程序开发更加高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值