C++学习之对象特性

简介: C++学习之对象特性

C++对象特性有哪些

C++ 是一种多范式编程语言,它提供了许多特性来支持面向对象编程。下面是 C++ 中常见的对象特性:

  1. 封装(Encapsulation):将数据和操作数据的方法打包在一起,对外部隐藏对象的内部实现细节,只暴露必要的接口给外部使用。
  2. 继承(Inheritance):允许一个类(子类)继承另一个类(父类)的属性和行为,通过这种方式可以实现代码的重用和扩展。
  3. 多态(Polymorphism):允许以统一的方式处理不同类型和不同类的对象,通过函数重载、运算符重载和虚函数实现多态性。
  4. 抽象(Abstraction):隐藏对象复杂性的某些部分,只显示对象的关键特征,使得对象更易于理解和使用。
  5. 类与对象:类是对象的模板,定义了描述对象行为和状态的成员变量和成员函数;对象是类的实例化,具体存在并可以被使用。
  6. 构造函数与析构函数:构造函数用于初始化对象的状态,在对象创建时自动调用;析构函数用于清理对象分配的资源,在对象销毁时自动调用。
  7. 成员访问控制:通过访问修饰符(public、private、protected)控制成员变量和成员函数的访问权限,保证数据的安全性。
  8. 友元类和友元函数:友元类或友元函数可以访问类的私有成员,这在某些情况下提供了更灵活的访问权限。
  9. 静态成员:静态成员变量和静态成员函数属于类本身,而不是属于类的实例,可以通过类名直接访问,用于表示与类相关的共享属性和方法。

这些是 C++ 中常见的对象特性,它们使得 C++ 成为一种强大的面向对象编程语言,可以更好地组织和管理复杂的程序结构。

C++对象:构造函数和析构函数

构造函数和析构函数是 C++ 中的特殊成员函数,用于在对象生命周期的不同阶段执行初始化和清理操作。下面是构造函数和析构函数的各种情况以及相应的代码示例:

  1. 默认构造函数(Default Constructor):当对象被创建时,如果没有显式提供构造函数,则会自动调用默认构造函数。默认构造函数不带任何参数。
class MyClass {
public:
    // 默认构造函数
    MyClass() {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 调用默认构造函数创建对象
    MyClass obj;
    return 0;
}
  1. 有参构造函数(Parameterized Constructor):当对象被创建时,可以使用提供参数的构造函数进行初始化。
class MyClass {
public:
    // 有参构造函数
    MyClass(int value) {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 调用有参构造函数创建对象并传递参数
    MyClass obj(10);
    return 0;
}
  1. 拷贝构造函数(Copy Constructor):当一个对象通过另一个对象进行初始化时,拷贝构造函数会被调用。
class MyClass {
public:
    // 拷贝构造函数
    MyClass(const MyClass& other) {
        // 构造函数的代码逻辑
    }
};
int main() {
    MyClass obj1;
    // 使用拷贝构造函数将 obj1 初始化为 obj2
    MyClass obj2(obj1);
    return 0;
}
  1. 移动构造函数(Move Constructor):当一个对象通过右值引用进行初始化时,移动构造函数会被调用。移动构造函数通常用于提高性能和资源管理。
class MyClass {
public:
    // 移动构造函数
    MyClass(MyClass&& other) {
        // 构造函数的代码逻辑
    }
};
int main() {
    MyClass obj1;
    // 使用移动构造函数将 obj1 移动到 obj2
    MyClass obj2(std::move(obj1));
    return 0;
}
  1. 析构函数(Destructor):在对象销毁时,析构函数会被自动调用,用于执行对象的清理操作。
class MyClass {
public:
    // 析构函数
    ~MyClass() {
        // 析构函数的代码逻辑
    }
};
int main() {
    // 创建对象
    MyClass obj;
    // 对象销毁时,析构函数被调用
    return 0;
}

这些是构造函数和析构函数的各种情况和相应的代码举例。根据具体的需求和实际情况,您可以选择适合的构造函数和析构函数来进行对象的初始化和清理操作。

C++对象:函数的分类和调用

在 C++ 中,函数可以根据其定义位置和用途进行分类。下面是常见的函数分类以及相应的调用情况和代码示例:

  1. 成员函数(Member Functions):定义在类内部的函数称为成员函数,它们可以访问类的成员变量,并提供了对象操作和行为的封装。
class MyClass {
public:
    // 成员函数
    void memberFunction() {
        // 函数的代码逻辑
    }
};
int main() {
    MyClass obj;
    // 对象调用成员函数
    obj.memberFunction();
    return 0;
}
  1. 静态成员函数(Static Member Functions):静态成员函数属于类本身,而不属于类的实例,可以通过类名直接调用而无需创建对象。
class MyClass {
public:
    // 静态成员函数
    static void staticFunction() {
        // 函数的代码逻辑
    }
};
int main() {
    // 直接调用静态成员函数
    MyClass::staticFunction();
    return 0;
}
  1. 友元函数(Friend Functions):友元函数是定义在类外部但具有对类私有成员访问权限的函数。
class MyClass {
private:
    int privateData;
public:
    friend void friendFunction(MyClass& obj);
};
// 友元函数可以访问私有成员
void friendFunction(MyClass& obj) {
    obj.privateData = 10;
}
int main() {
    MyClass obj;
    // 调用友元函数
    friendFunction(obj);
    return 0;
}
  1. 构造函数(Constructors):构造函数用于对象的初始化,在对象创建时自动调用。
class MyClass {
public:
    // 构造函数
    MyClass() {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 创建对象时自动调用构造函数
    MyClass obj;
    return 0;
}
  1. 析构函数(Destructor):析构函数在对象销毁时自动调用,用于执行对象的清理操作。
class MyClass {
public:
    // 析构函数
    ~MyClass() {
        // 析构函数的代码逻辑
    }
};
int main() {
    MyClass obj;
    // 对象销毁时自动调用析构函数
    return 0;
}
  1. 运算符重载函数(Operator Overloading):通过定义特定名称的函数来重载运算符,扩展了原生的操作符的功能。
class MyClass {
public:
    int data;
    // 运算符重载函数
    MyClass operator+(const MyClass& other) {
        MyClass result;
        result.data = this->data + other.data;
        return result;
    }
};
int main() {
    MyClass obj1;
    obj1.data = 5;
    MyClass obj2;
    obj2.data = 10;
    // 调用运算符重载函数
    MyClass sum = obj1 + obj2;
    return 0;
}

C++对象:构造函数调用规则

在C++中,构造函数的调用规则可以根据不同情况进一步详细说明。以下是构造函数调用规则的各种情况和相应的代码示例:

  1. 默认构造函数的调用:如果没有显式提供构造函数,系统会自动生成默认构造函数并在对象创建时自动调用。
class MyClass {
public:
    // 默认构造函数
    MyClass() {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 调用默认构造函数创建对象
    MyClass obj;
    return 0;
}
  1. 有参构造函数的调用:提供参数的构造函数将在对象创建时调用,并根据传入的参数进行初始化。
class MyClass {
public:
    // 有参构造函数
    MyClass(int value) {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 调用有参构造函数创建对象并传递参数
    MyClass obj(10);
    return 0;
}
  1. 拷贝构造函数的调用:当一个对象通过另一个对象进行初始化时,拷贝构造函数会被调用。
class MyClass {
public:
    // 拷贝构造函数
    MyClass(const MyClass& other) {
        // 构造函数的代码逻辑
    }
};
int main() {
    MyClass obj1;
    // 使用拷贝构造函数将 obj1 初始化为 obj2
    MyClass obj2(obj1);
    return 0;
}
  1. 移动构造函数的调用:当一个对象通过右值引用进行初始化时,移动构造函数会被调用。
class MyClass {
public:
    // 移动构造函数
    MyClass(MyClass&& other) {
        // 构造函数的代码逻辑
    }
};
int main() {
    MyClass obj1;
    // 使用移动构造函数将 obj1 移动到 obj2
    MyClass obj2(std::move(obj1));
    return 0;
}
  1. 显式调用构造函数:可以通过直接调用构造函数来创建对象,这种情况下会显式调用构造函数。
class MyClass {
public:
    // 有参构造函数
    MyClass(int value) {
        // 构造函数的代码逻辑
    }
};
int main() {
    // 显式调用构造函数创建对象
    MyClass obj = MyClass(20);
    return 0;
}

C++对象:深拷贝和浅拷贝

在C++中,深拷贝和浅拷贝是用来描述在对象复制时对内存中数据的不同处理方式。下面解释深拷贝和浅拷贝的概念,并提供各种情况和代码示例:

  1. 浅拷贝(Shallow Copy):浅拷贝只是简单地复制对象的值,如果对象包含指针变量,则仅复制指针地址,而不复制指针指向的实际内容。这可能导致多个对象共享相同的内存空间,一次修改可能会影响到其他对象。

示例代码:

#include <iostream>
#include <cstring>
class ShallowCopy {
private:
    char *data;
public:
    // 构造函数
    ShallowCopy(const char* value) {
        data = new char[strlen(value) + 1];
        strcpy(data, value);
    }
    // 拷贝构造函数(浅拷贝)
    ShallowCopy(const ShallowCopy& other) {
        data = other.data;
    }
    // 打印数据
    void printData() {
        std::cout << "Data: " << data << std::endl;
    }
};
int main() {
    ShallowCopy obj1("Hello");
    // 浅拷贝创建新对象 obj2
    ShallowCopy obj2 = obj1;
    obj1.printData();  // 输出 "Data: Hello"
    obj2.printData();  // 输出 "Data: Hello"
    // 修改 obj1 的数据
    obj1.printData();  // 输出 "Data: Bye"
    obj2.printData();  // 输出 "Data: Bye"
    return 0;
}
  1. 深拷贝(Deep Copy):深拷贝会复制对象的所有数据,包括指针指向的内存块,这样每个对象都有自己独立的内存空间,互不影响。

示例代码:

#include <iostream>
#include <cstring>
class DeepCopy {
private:
    char *data;
public:
    // 构造函数
    DeepCopy(const char* value) {
        data = new char[strlen(value) + 1];
        strcpy(data, value);
    }
    // 深拷贝构造函数
    DeepCopy(const DeepCopy& other) {
        data = new char[strlen(other.data) + 1];
        strcpy(data, other.data);
    }
    // 打印数据
    void printData() {
        std::cout << "Data: " << data << std::endl;
    }
    // 析构函数
    ~DeepCopy() {
        delete[] data;
    }
};
int main() {
    DeepCopy obj1("Hello");
    // 深拷贝创建新对象 obj2
    DeepCopy obj2 = obj1;
    obj1.printData();  // 输出 "Data: Hello"
    obj2.printData();  // 输出 "Data: Hello"
    // 修改 obj1 的数据
    obj1.printData();  // 输出 "Data: Bye"
    obj2.printData();  // 输出 "Data: Hello"
    return 0;
}

以上代码,可以看出浅拷贝和深拷贝之间的区别。

C++对象:初始化和初始化列表的各种情况

在C++中,对象的初始化可以通过构造函数中的初始化列表来实现,也可以在构造函数内部通过赋值语句进行初始化。下面将介绍对象的初始化和初始化列表的各种情况,并提供相应的代码示例:

  1. 使用初始化列表进行初始化:初始化列表在构造函数参数后使用冒号进行指定,可以在对象创建时直接对成员变量进行初始化,提高效率。
#include <iostream>
class InitListExample {
private:
    int a;
    int b;
public:
    // 构造函数使用初始化列表进行初始化
    InitListExample(int x, int y) : a(x), b(y) {
        // 可以在此处添加其他初始化逻辑
    }
    void printData() {
        std::cout << "a: " << a << ", b: " << b << std::endl;
    }
};
int main() {
    InitListExample obj(10, 20);
    obj.printData(); // 输出 "a: 10, b: 20"
    return 0;
}
  1. 在构造函数内部进行赋值初始化:如果没有使用初始化列表,也可以在构造函数内部使用赋值语句对成员变量进行初始化。
#include <iostream>
class AssignmentInitExample {
private:
    int a;
    int b;
public:
    // 构造函数内部进行赋值初始化
    AssignmentInitExample(int x, int y) {
        a = x;
        b = y;
    }
    void printData() {
        std::cout << "a: " << a << ", b: " << b << std::endl;
    }
};
int main() {
    AssignmentInitExample obj(30, 40);
    obj.printData(); // 输出 "a: 30, b: 40"
    return 0;
}
  1. 初始化列表与默认参数的结合:初始化列表还可以与默认参数结合使用,在构造函数中指定默认值并且通过初始化列表进行初始化。
#include <iostream>
class DefaultParamInitExample {
private:
    int a;
    int b;
public:
    // 使用初始化列表与默认参数结合进行初始化
    DefaultParamInitExample(int x = 0, int y = 0) : a(x), b(y) {
        // 可以在此处添加其他初始化逻辑
    }
    void printData() {
        std::cout << "a: " << a << ", b: " << b << std::endl;
    }
};
int main() {
    DefaultParamInitExample obj1;
    obj1.printData(); // 输出 "a: 0, b: 0"
    DefaultParamInitExample obj2(50, 60);
    obj2.printData(); // 输出 "a: 50, b: 60"
    return 0;
}

以上代码示例,可以看到不同情况下如何使用初始化列表或在构造函数内部进行初始化,以及初始化列表与默认参数的结合使用。

C++对象:类对象作为类成员

在C++中,类对象可以作为类的成员变量,这样可以实现更复杂的数据结构和功能组合。下面将介绍类对象作为类成员的各种情况,并提供相应的代码示例:

  1. 类对象作为类的非静态成员:类对象可以作为类的非静态成员,在构造函数中进行初始化。
#include <iostream>
class InnerClass {
public:
    void printHello() {
        std::cout << "Hello from InnerClass!" << std::endl;
    }
};
class OuterClass {
private:
    InnerClass inner;
public:
    OuterClass() {
        // 可以在构造函数中对 inner 进行初始化
    }
    void callInner() {
        inner.printHello();
    }
};
int main() {
    OuterClass obj;
    obj.callInner(); // 输出 "Hello from InnerClass!"
    return 0;
}
  1. 类对象作为类的静态成员:类对象还可以作为类的静态成员,所有类的对象会共享静态成员。
#include <iostream>
class StaticClass {
public:
    static int count; // 静态成员变量
    void printCount() {
        std::cout << "Count: " << count << std::endl;
    }
};
int StaticClass::count = 0; // 静态成员变量初始化
class OuterClass {
public:
    static StaticClass obj; // 静态成员对象
};
StaticClass OuterClass::obj; // 静态成员对象定义
int main() {
    OuterClass::obj.count = 10;
    OuterClass obj1;
    OuterClass obj2;
    obj1.obj.printCount(); // 输出 "Count: 10"
    obj2.obj.printCount(); // 输出 "Count: 10"
    obj1.obj.count = 20;
    obj1.obj.printCount(); // 输出 "Count: 20"
    obj2.obj.printCount(); // 输出 "Count: 20"
    return 0;
}

通过以上代码示例,可以看到类对象作为类成员的两种情况。

关注我,不迷路,共学习,同进步

关注我,不迷路,共学习,同进步

相关文章
|
3月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
27天前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
54 12
|
2月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
2月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
3月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
2月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
4月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
124 19
|
3月前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
3月前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
4月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
84 16