C++ 钻石问题

C++ 钻石问题

当使用多重继承时,计算机语言中可能会出现钻石问题,特别是在C++中。当代码非常复杂时,C++中经常使用多重继承作为一种技术。因此,为了组织程序和源代码,我们使用类。然而,如果不适当处理,多重继承可能会有问题。钻石问题主要存在于这些困惑中。本课程重点介绍了钻石问题的主要原因,以及它是如何由多重继承导致的,以及解决它所需的所有方法。

代码的系统要求

为了在Linux操作系统下运行与”C++钻石继承”相关的应用程序,您需要在虚拟机上安装和运行一个Ubuntu系统。它需要两个工具。一个是任何编辑工具;因此,我们将使用Linux内置的”文本编辑器”。其他喜欢的编辑工具也是可以找到的。Ubuntu终端是第二个工具,您将使用它来运行程序并查看输出。由于在源代码中存在继承时会出现”钻石问题”,所以我们将首先在本文中讨论多重继承。

多重继承

举个例子,在现实世界中,如果一个母亲和一个父亲生下一个孩子,那么孩子将从父母那里继承一切。因此,可以认为这个孩子的母亲和父亲是派生类。回到各种继承,让我们继续。在本次讨论中,将使用”构造函数”。当存在多个继承时,继承类(子类)的构造函数按照祖先的顺序运行。然而,对于析构函数,继承顺序被颠倒。现在,我们将使用一个简单的示例来说明C++中的继承工作原理。

由于C++具有多重继承的特性,一个类可以从多个类继承。继承类的构造函数的调用顺序与它们被继承的顺序相同。例如,在下面的程序中,先调用second类的构造函数,然后是A类的构造函数。

一个类可以从多个基类派生。

示例:

  • FATHER和MOTHER类是CHILD类的祖先。
  • LIQUID和FUEL类产生PETROL类。
class A
{ 
// ,,,,,,,,,,,,,
};
class B
{
// ,,,,,,,,,,,,,,
};
class C: public A,public B
{
// ,,,,,,,,,,,,,
};

让我们看一个例子来更好地理解这个概念:

# include < iostream >
using namespace std ;
class one
{
public:
one ( ) { cout << " one's constructor is called here " << endl ; }
} ;
class two
{
public:
two ( ) { cout << "two's constructor is called here " << endl ; }
} ;
class three : public two , public one // Note the order
{
public:
three ( ) { cout << " C's constructor called " << endl ; }
} ;
int main()
{
    three th ;
    return 0 ; 
}

输出:

two's constructor is called here
one's constructor is called here
three's constructor is called here
?????????????????..
Process executed in 0.11 seconds
Press any key continue.

析构函数在构造函数之后以相反的顺序被调用。

钻石问题: 当一个类的两个父类共享一个基类时,就会出现钻石问题。例如,在下面的图表中,TA类从Person类中接收到了每个属性的两个副本,这导致了歧义。例如,请考虑以下程序。

# include < iostream >
using namespace std ;
class Base {
// Data members of Base class
public :
    Base ( int a ) { cout < < " Base :: Base ( int ) called " < < endl ; }
} ;
class Derived : public Base {
// data members of Derived
public :
    Derived ( int a ) : Base ( a ) {
    cout < < " Derived :: Derived ( int ) called " < < endl ;
    }
} ;
class Derived_2 : public Base {
// data members of Derived_2
public :
    Derived_2 ( int a ) : Base ( a ) {
        cout < < " Derived_2 :: Derived_2 ( int ) called " < < endl ;
    }
} ;
class Result : public Derived , public Derived_2 {
public :
    Result ( int a ) : Derived_2 ( a ) , Derived ( a ) {
        cout < < " Result :: Result ( int ) called " < < endl ;
    }
} ;
int main ( ) {
    Result rs1 ( 30 ) ;
}

输出:

Base :: Base ( int ) called
Derived :: Derived ( int ) called
Base :: Base ( int ) called
Derived_2 :: Derived_2 ( int ) called
Result :: Result ( int ) called
?????????????????..
Process executed in 0.11 seconds
Press any key continue.

解释

上述代码中调用了两次类”Base”。当对象”rs1″被销毁时,”Base”的析构函数也将被调用两次。由于对象”rs1″包含了两个”Base”元素,导致了混乱。为了防止在”Result”类中出现两个”Base”实例,我们使用了”virtual”这个关键词。为了解决这个问题,我们创建了虚基类”Derived”和”Derived_2″。例如,考虑下面的程序。

# include < iostream >
using namespace std ;
class Base {
public :
    Base ( int x ) { cout < < " Base :: Base ( int ) is called " < < endl ; }
    Base ( ) { cout < < "Base :: Base ( ) is called " < < endl ; }
} ;
class Derived : virtual public Base {
public :
    Derived ( int a ) :: Base ( a ) {
    cout < < "Derived :: Derived ( int ) is called " < < endl ;
    }
} ;
class Derived_1 : virtual public Derived {
public :
    Derived_1 ( int a ) : Derived ( a ) {
        cout < < " Derived_1 :: Derived_1 ( int ) is called " < < endl ;
    }
} ;
class Result : public Derived_1 , public Derived {
public :
    Result ( int a ) : Derived_1 ( a ) , Derived ( a ) {
        cout < < " Result :: Result ( int ) is called " < < endl ;
    }
} ;
int main ( ) {
    Result rs1 ( 30 ) ;
}

输出:

Base :: Base ( ) is called
Derived :: Derived ( int ) is called
Derived_1 :: Derived_1 ( int ) is called
Result :: Result ( int ) is called  
?????????????????..
Process executed in 0.11 seconds
Press any key continue.

解释

在上面的程序中,对“Person”的函数Object() { [native code]}进行了一次调用。需要注意的是,在上述输出中调用了“Person”的默认函数Object() { [native code]}是至关重要的。即使父类明确调用参数化函数Object() {[native code]}时,使用“virtual”关键字时默认调用祖父类的默认函数Object() {[native code]}。如何使用“Person”类的参数化函数Object() {[native code]}?在“TA”类中,必须调用函数Object() {[native code]}。以下是一个示例软件。

# include < iostream >
using namespace std ;
class Base {
public :
Base ( int a ) { cout < < " Base :: Base ( int ) is called " < < endl ; }
Base () { cout < < " Base :: Base ( ) is called " < < endl ; }
} ;
class Derived : virtual public Base {
public :
Derived ( int a ) : Person ( a ) {
cout < < " Derived :: Derived ( int ) is called " < < endl ;
}
} ;
Class Derived_1 : virtual public Derived {
public :
Derived_1 ( int a ) : Derived ( a ) {
cout < < " Derived_1 :: Derived_1 ( int ) is called " < < endl ;
}
} ;
class Result : public Derived_1 , public Derived {
public :
Result ( int a ) : Derived ( a ) , Derived ( a ) , Base ( a ) {
cout < < " Result :: Result ( int ) is called " < < endl ;
}
} ; 
int main ( ) {
Result rs1 ( 30 ) ;
}

输出:

Base :: Base ( int ) is called
Derived :: Derived ( int ) is called
Derived_1 :: Derived_1 ( int ) is called
Result :: Result ( int ) is called
?????????????????..
Process executed in 0.11 seconds
Press any key continue.

解释

通常情况下,必须通过父类而不是直接调用祖父类的 Object() { [native code] } 函数。只有在使用关键字 “virtual” 时才允许直接调用。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程