C/C++编程笔记:高级C++知识 | 虚拟构造器

Posted 一起学编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++编程笔记:高级C++知识 | 虚拟构造器相关的知识,希望对你有一定的参考价值。

我们可以在C ++中使类构造函数虚拟化以创建多态对象吗?不会。C++是静态类型的(RTTI的目的有所不同)语言,对于C ++编译器来说,多态创建对象是没有意义的。编译器必须知道创建对象的类类型。换句话说,从C ++编译器的角度来看,要创建哪种类型的对象是编译时的决定。如果我们将构造函数设为虚拟,则编译器会标记错误。实际上,除了inline之外,构造函数的声明中不允许其他关键字。

在实际情况下,我们需要基于一些输入在类层次结构中创建派生类对象。换句话说,对象创建和对象类型紧密耦合,这迫使修改扩展。虚拟构造器的目的是使对象创建与类型脱钩

我们如何在运行时创建所需的对象类型?例如,请参见下面的示例程序。

#include <iostream>

using namespace std;

 LIBRARY START

class Base

{

public:

Base() { }

virtual // Ensures to invoke actual object destructor

~Base() { }

// An interface

virtual void DisplayAction() = 0;

};

class Derived1 : public Base

{

public:

Derived1()

{

cout << "Derived1 created" << endl;

}

~Derived1()

{

cout << "Derived1 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived1" << endl;

}

};

class Derived2 : public Base

{

public:

Derived2()

{

cout << "Derived2 created" << endl;

}

~Derived2()

{

cout << "Derived2 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived2" << endl;

}

};

 LIBRARY END

class User

{

public:

// Creates Drived1

User() : pBase(nullptr)

{

// What if Derived2 is required? - Add an if-else ladder (see next sample)

pBase = new Derived1();

}

~User()

{

if( pBase )

{

delete pBase;

pBase = nullptr;

}

}

// Delegates to actual object

void Action()

{

pBase->DisplayAction();

}

private:

Base *pBase;

};

int main()

{

User *user = new User();

// Need Derived1 functionality only

user->Action();

delete user;

}

在以上示例中,假定层次结构BaseDerived1Derived2是库代码的一部分。User类是试图利用层次结构的实用程序类。的主要功能是消耗基地经由层级的功能 的用户 类。

用户类构造函数创建Derived1对象,始终。如果用户的使用者(在我们的例子中是主要用户)需要Derived2功能,则用户需要创建“ new Derived2() ”并强制重新编译。重新编译是不好的设计方法,因此我们可以选择以下方法。

在详细介绍之前,让我们回答一下,谁将指示创建Derived1Derived2对象?显然,它是User类的使用者。该用户类可以使用的if-else梯的创建或者Derived1Derived2的,如下面的示例所示:

#include <iostream>

using namespace std;

 LIBRARY START

class Base

{

public:

Base() { }

virtual // Ensures to invoke actual object destructor

~Base() { }

// An interface

virtual void DisplayAction() = 0;

};

class Derived1 : public Base

{

public:

Derived1()

{

cout << "Derived1 created" << endl;

}

~Derived1()

{

cout << "Derived1 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived1" << endl;

}

};

class Derived2 : public Base

{

public:

Derived2()

{

cout << "Derived2 created" << endl;

}

~Derived2()

{

cout << "Derived2 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived2" << endl;

}

};

 LIBRARY END

class User

{

public:

// Creates Derived1 or Derived2 based on input

User() : pBase(nullptr)

{

int input; // ID to distinguish between

// Derived1 and Derived2

cout << "Enter ID (1 or 2): ";

cin >> input;

while( (input != 1) && (input != 2) )

{

cout << "Enter ID (1 or 2 only): ";

cin >> input;

}

if( input == 1 )

{

pBase = new Derived1;

}

else

{

pBase = new Derived2;

}

// What if Derived3 being added to the class hierarchy?

}

~User()

{

if( pBase )

{

delete pBase;

pBase = nullptr;

}

}

// Delegates to actual object

void Action()

{

pBase->DisplayAction();

}

private:

Base *pBase;

};

int main()

{

User *user = new User();

// Need either Derived1 or Derived2 functionality

user->Action();

delete user;

}

上面的代码*不*开放扩展,这是一种不灵活的设计。简而言之,如果库使用新类Derived3更新类层次结构。User类如何创建Derived3对象?一种方法是更新基于新输入ID 3来创建Derived3对象的if-else阶梯,如下所示,

#include <iostream>

using namespace std;

class User

{

public:

User() : pBase(nullptr)

{

// Creates Drived1 or Derived2 based on need

int input; // ID to distinguish between

// Derived1 and Derived2

cout << "Enter ID (1 or 2): ";

cin >> input;

while( (input != 1) && (input != 2) )

{

cout << "Enter ID (1 or 2 only): ";

cin >> input;

}

if( input == 1 )

{

pBase = new Derived1;

}

else if( input == 2 )

{

pBase = new Derived2;

}

else

{

pBase = new Derived3;

}

}

~User()

{

if( pBase )

{

delete pBase;

pBase = nullptr;

}

}

// Delegates to actual object

void Action()

{

pBase->DisplayAction();

}

private:

Base *pBase;

};

上面的修改迫使User类的用户重新编译,不好的(不灵活的)设计!并且不会因基础扩展而关闭用户类的进一步修改。

问题在于对象的创建。将新类添加到层次结构中,从而强制重新编译User类的依赖项。我们不能将创建对象的操作委托给类层次结构本身或虚拟行为的函数吗?通过将对象创建委托给类层次结构(或静态函数),我们可以避免UserBase层次结构之间的紧密耦合。理论足够,请参见以下代码,

#include <iostream>

using namespace std;

 LIBRARY START

class Base

{

public:

// The "Virtual Constructor"

static Base *Create(int id);

Base() { }

virtual // Ensures to invoke actual object destructor

~Base() { }

// An interface

virtual void DisplayAction() = 0;

};

class Derived1 : public Base

{

public:

Derived1()

{

cout << "Derived1 created" << endl;

}

~Derived1()

{

cout << "Derived1 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived1" << endl;

}

};

class Derived2 : public Base

{

public:

Derived2()

{

cout << "Derived2 created" << endl;

}

~Derived2()

{

cout << "Derived2 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived2" << endl;

}

};

class Derived3 : public Base

{

public:

Derived3()

{

cout << "Derived3 created" << endl;

}

~Derived3()

{

cout << "Derived3 destroyed" << endl;

}

void DisplayAction()

{

cout << "Action from Derived3" << endl;

}

};

// We can also declare "Create" outside Base

// But it is more relevant to limit it's scope to Base

Base *Base::Create(int id)

{

// Just expand the if-else ladder, if new Derived class is created

// User code need not be recompiled to create newly added class objects

if( id == 1 )

{

return new Derived1;

}

else if( id == 2 )

{

return new Derived2;

}

else

{

return new Derived3;

}

}

 LIBRARY END

 UTILITY START

class User

{

public:

User() : pBase(nullptr)

{

// Receives an object of Base hierarchy at runtime

int input;

cout << "Enter ID (1, 2 or 3): ";

cin >> input;

while( (input != 1) && (input != 2) && (input != 3) )

{

cout << "Enter ID (1, 2 or 3 only): ";

cin >> input;

}

// Get object from the "Virtual Constructor"

pBase = Base::Create(input);

}

~User()

{

if( pBase )

{

delete pBase;

pBase = nullptr;

}

}

// Delegates to actual object

void Action()

{

pBase->DisplayAction();

}

private:

Base *pBase;

};

 UTILITY END

 Consumer of User (UTILITY) class

int main()

{

User *user = new User();

// Action required on any of Derived objects

user->Action();

delete user;

}

用户类是独立的对象创建的。它将责任委托给Base,并以ID的形式提供输入。如果库添加了新的类Derived4,则库修改器将扩展Create内的if-else梯形图以返回正确的对象。消费者用户不需要重新编译他们的代码由于延长基地

请注意,函数Create用于在运行时返回不同类型的类对象。它的作用类似于虚拟构造函数,在模式术语中也称为Factory Method

模式世界展示了实现上述概念的不同方法。

以上就是今天的全部内容了。每日分享小知识,希望对你有帮助~

另外如果你想更好的提升你的编程能力,学好C语言C++编程!弯道超车,快人一步!笔者这里或许可以帮到你~

C语言C++编程学习交流圈子,QQ群:765803539点击进入】微信公众号:C语言编程学习基地

分享(源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

编程学习视频分享:

 

以上是关于C/C++编程笔记:高级C++知识 | 虚拟构造器的主要内容,如果未能解决你的问题,请参考以下文章

C/C++编程笔记:C++多态性知识详解

C/C++编程笔记:用C++编写赋值运算符,一般什么情况下用?

C++面向对象高级编程(上) 第三周笔记 GeekBand

Java7编程高级进阶学习笔记

C/C++编程笔记:C++中的函数重载和浮动

C/C++编程笔记:C++中的函数重载