C++三大特性及代码示例【封装、继承、多态】

封装

C++的封装体现在类中。封装是指将数据和操作数据的函数绑定在一起,形成一个单元12。这样可以保护数据的安全性,防止被外部访问或修改

C++中使用访问修饰符来实现封装。有三种访问修饰符:private、protected和public13。默认情况下,类中的所有数据成员和成员函数都是私有的,只能在类内部访问1。如果想要提供一个接口给外部访问或修改数据,可以使用公有的成员函数32

// 封装示例
#include <iostream>
using namespace std;

// 定义一个圆类
class Circle {
  private:
    // 私有数据成员
    double radius;
  public:
    // 公有构造函数
    Circle(double r) {
      radius = r;
    }
    // 公有成员函数
    double getArea() {
      return 3.14 * radius * radius;
    }
};

int main() {

  // 创建一个圆对象
  Circle c(5);

  // 调用公有成员函数获取面积
  cout << "Area = " << c.getArea() << endl;

  // 尝试直接访问私有数据成员(会报错)
  // cout << "Radius = " << c.radius << endl;

  return 0;
}

private

C++中的private是一种访问修饰符,它用于限制类成员的可见性和可访问性。private成员只能被该类中的其他成员函数和友元函数访问,不能被该类的对象或外部函数直接访问123。这是C++实现数据封装和隐藏的一种方式14。。

public

所有声明为public的类成员都可以被任何人访问。声明为public的数据成员和成员函数可以被其他类访问123。这是C++实现数据共享和继承的一种方式24

protected

protected是一种访问修饰符,用来定义类中的受保护成员(数据和函数)。受保护成员只能被以下方式访问:

  • 声明这些成员的类的成员函数

  • 声明这些成员的类的友元

  • 继承自声明这些成员的类的子类的成员函数或友元

// protected示例
#include <iostream>
using namespace std;

// 定义一个基类
class Base 
{
  protected:
    // 受保护数据成员
    int x;
  public:
    // 公有构造函数
    Base(int a) {
      x = a;
    }
};

// 定义一个派生类
class Derived: public Base 
{
  public:
    // 公有构造函数
    Derived(int b): Base(b) {}
    // 公有成员函数,可以访问基类的受保护数据成员x
    void showX() {
      cout << "x = " << x << endl;
    }
};

int main() {

  // 创建一个派生类对象
  Derived d(10);

  // 调用公有成员函数显示x的值
  d.showX();

  // 尝试直接访问基类的受保护数据成员x(会报错)
  // cout << "x = " << d.x << endl;

  return 0;
}

友元函数:

#include <iostream>
using namespace std;
class A
{
private:
    int x; // 私有成员
public:
    A(int value)
    {
        x = value; // 构造函数
    }
    friend void printX(A a); // 声明友元函数
};

// 定义友元函数,可以访问A类的私有成员
void printX(A a)
{
    cout << a.x; // 可以访问a.x,因为printX是A类的友元函数
}

int main()
{
    A a(10);   // 创建A类的对象
    printX(a); // 调用友元函数,输出10
    return 0;
}

继承

C++的继承体现在类之间。继承是指从一个已有的类(基类)创建一个新的类(派生类)。派生类继承了基类的特征,并且可以有自己的特征1

继承可以实现代码的复用和扩展,也可以体现对象之间的层次关系

单继承

// 继承示例
#include <iostream>
using namespace std;

// 定义一个动物类
class Animal {
  protected:
    // 受保护数据成员
    string name;
  public:
    // 公有构造函数
    Animal(string n) {
      name = n;
    }
    // 公有成员函数,显示动物的名字
    void showName() {
      cout << "I am " << name << endl;
    }
};

// 定义一个狗类,继承自动物类
class Dog: public Animal {
  public:
    // 公有构造函数,调用基类的构造函数初始化name
    Dog(string n): Animal(n) {}
    // 公有成员函数,显示狗的叫声
    void bark() {
      cout << "Woof! Woof!" << endl;
    }
};

int main() {

  // 创建一个狗对象
  Dog d("Jack");

  // 调用公有成员函数显示名字和叫声
  d.showName();
  d.bark();

  return 0;
}

多继承

C++支持多重继承,这是指一个类可以从多个基类继承特征和行为。在多重继承中,派生类的构造函数会按照基类的继承顺序依次调用

// Base class
#include <iostream>
using namespace std;
class Mammal
{
public:
    void mammalFunction()
    {
        cout << "I am a mammal." << endl;
    }
};

// Another base class
class WingedAnimal
{
public:
    void wingedAnimalFunction()
    {
        cout << "I have wings." << endl;
    }
};

// Derived class
class Bat : public Mammal, public WingedAnimal
{
};

int main()
{
    Bat myBat;

    myBat.mammalFunction();
    myBat.wingedAnimalFunction();
    return 0;
}

多态

多态有两种主要的形式:编译时多态和运行时多态。

编译时多态

编译时多态(或静态多态)是指在编译阶段就确定了函数或运算符的具体形式。这种多态是通过函数重载运算符重载来实现的。例如,我们可以根据参数的个数和类型来定义不同的add()函数。

函数重载
// function with int parameters
int sum (int a, int b)
{
  return a + b;
}

// function with double parameters
double sum (double a, double b)
{
  return a + b;
}

int main ()
{
  cout << sum (10,20) << '\n'; // calls int version
  cout << sum (1.0,1.5) << '\n'; // calls double version
  return 0;
}
运算符重载:
#include <iostream>
using namespace std;

class String {
   private:
    char* s;
    int size;

   public:
    String(const char* s) {
        size = strlen(s);
        this->s = new char[size + 1];
        strcpy(this->s, s);
    }

    // overload + operator
    String operator+(const String& obj) {
        int len = size + obj.size;
        char* temp = new char[len + 1];
        strcpy(temp, s);
        strcat(temp, obj.s);

        return String(temp);
    }

    void print() { cout << s << endl; }
};

int main() {
    String s1("Hello");
    String s2("World");
    
    // concatenate two strings using +
    String s3 = s1 + s2;
    
    // print the concatenated string
    s3.print();

    return 0;
}

运行时多态

运行时多态(或动态多态)是指在运行阶段才确定了函数或运算符的具体形式。这种多态是通过虚函数抽象类来实现的。例如,我们可以使用基类类型的指针或引用来调用不同子类对象的animalSound()函数。

虚函数:

允许定义一个通用父类,不同的子类继承它并可以实现其虚函数,适合在运行时候动态调用子类时使用,不需要预先确定子类是什么。因此虚函数调用在运行时确定,而不是编译时确定。

#include <iostream>
using namespace std;
class A
{
public:
    void foo()
    {
        cout << "A:foo() is called" << endl;
    }
};
class B : public A
{
public:
    void foo()
    {
        cout << "B foo() is called" << endl;
    }
};
class C : public A
{
public:
    void foo()
    {
        cout << "C foo() is called" << endl;
    }
};
int main()
{
    A *a = new B(); 
    A *a = new C(); 
    return 0;
}
抽象类:(C++中的接口)

C++中抽象类是指至少有一个纯虚函数的类12。纯虚函数是指没有定义的函数,只有声明1。例如,下面的代码展示了一个名为Shape的抽象类,它有一个纯虚函数area():

class Shape {
   public:
      // pure virtual function
      virtual double area() = 0;
};
// 两个从Shape派生出来的具体类Circle和Rectangle,它们都实现了area()函数
class Circle : public Shape {
   private:
      double radius;

   public:
      Circle(double r) { radius = r; }
      
      // override pure virtual function
      double area() { return 3.14 * radius * radius; }
};

class Rectangle : public Shape {
   private:
      double length;
      double width;

   public:
      Rectangle(double l, double w) { length = l; width = w; }
      
      // override pure virtual function
      double area() { return length * width; }
};

抽象类的目的是提供一个共同的基类,让多个派生类可以共享34。抽象类不能创建对象,只能用指针或引用来操作5。从抽象类派生出来的类必须实现纯虚函数,否则它们也会成为抽象类5

使用抽象类的好处是可以实现多态性,即用同一种方式处理不同类型的对象23。例如,下面的代码展示了如何用一个Shape指针数组来存储不同类型的形状,并调用它们各自的area()函数:

int main()
{
    // Shape s; // error: cannot declare variable 's' to be of abstract type 'Shape'

    // create an array of Shape pointers
    Shape* shapes[2];
    
    // assign different types of shapes to the array elements
    shapes[0] = new Circle(5.0);
    shapes[1] = new Rectangle(10.0, 20.0);
    
    // loop through the array and call area() function for each shape
    for (int i = 0; i < 2; i++) {
        cout << "The area of shape " << i << " is " << shapes[i]->area() << endl;
    }

    return 0;
}

C#中的接口:

// 定义一个接口,包含一个抽象方法
interface IAnimal
{
    void MakeSound();
}

// 定义一个类,实现接口
class Dog : IAnimal
{
    // 重写接口方法
    public void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

// 定义另一个类,实现接口
class Cat : IAnimal
{
    // 重写接口方法
    public void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}

// 在主程序中,创建不同的对象,并调用接口方法
class Program
{
    static void Main(string[] args)
    {
        IAnimal dog = new Dog();
        dog.MakeSound(); // 输出 Woof!

        IAnimal cat = new Cat();
        cat.MakeSound(); // 输出 Meow!
    }
}

Java中的接口

// 定义一个接口,包含两个抽象方法
interface Language {
    public void getType();
    public void getVersion();
}

// 定义一个类,实现接口
class Java implements Language {
    // 重写接口方法
    public void getType() {
        System.out.println("Java is an object-oriented language.");
    }

    public void getVersion() {
        System.out.println("The latest version of Java is 17.");
    }
}

// 定义另一个类,实现接口
class Python implements Language {
    // 重写接口方法
    public void getType() {
        System.out.println("Python is an interpreted language.");
    }

    public void getVersion() {
        System.out.println("The latest version of Python is 3.10.");
    }
}

// 在主程序中,创建不同的对象,并调用接口方法
class Main {
    public static void main(String[] args) {
        Language java = new Java();
        java.getType(); // 输出 Java is an object-oriented language.
        java.getVersion(); // 输出 The latest version of Java is 17.

        Language python = new Python();
        python.getType(); // 输出 Python is an interpreted language.
        python.getVersion(); // 输出 The latest version of Python is 3.10.
    }
}

猜你喜欢

转载自blog.csdn.net/cycler_725/article/details/129333948