C++中调用构造函数和调用构造函数的函数指针有什么区别

问题描述 投票:0回答:1

问这个问题的目的是为了加深我的理解。

我试图动态加载本机 DLL,并注意到一个我无法理解的现象。

因此,鉴于我的 DLL 具有以下过于简化的导出类。

ClassA {

    SubClassA subClass;

    ClassA() {
        subClass = new SubClassA;
    }

    ~ClassA() {
        delete subClass;
    }
}

我尝试了两种方法来链接到 DLL 并在单独的 C++ 控制台项目中调用构造函数:

方法一:静态链接(成功)

#include <ClassA.h>


void main() {

    ClassA* myClass;
    myClass = new ClassA();

}

方法 2:动态链接(因内存访问冲突而失败)

#include <ClassA.h>
#include <windows.h> 

void main() {

    HMODULE m_NativeLibraryHandle;
    
    ClassA* myClass;
    typedef ClassA* (__stdcall* ClassAConstructor)();
    ClassAConstructor p_Constructor;

    m_NativeLibraryHandle = ::LoadLibrary(L"ClassA.dll");
    p_Constructor = (ClassAConstructor)GetProcAddress(m_NativeLibraryHandle, "decoratedNameofConstructor");

    myClass = p_Constructor();
}

在 DLL 项目中调试显示,在

subClass = new SubClassA;
处引发了违规,其中
this
指针显示“无法读取”。 (我的猜测是
new SubClassA
未能分配给
subClass
。)

上述两种方法之间的实际差异是什么导致了行为的不同?我的理解是,

LoadLibrary
GetProcAddress
基本上做的是Linker正在做的事情,所以理论上它们应该表现相似。

c++ winapi dll constructor function-pointers
1个回答
0
投票

在 C++ 中调用 a 构造函数和调用 a 构造函数的函数指针的区别nce如下:

  • C++ 中不能调用构造函数。
  • C++ 中不存在构造函数的函数指针。

您无法在 C++ 中调用构造函数。当您使用

new
关键字、在堆栈上声明对象等时,该语言会为您执行此操作。构造
new MyClass()
可能看起来像构造函数调用,实际上它确实 包含 一个构造函数调用,因此可能会被误认为是构造函数调用,但事实并非如此;它是一个新的对象表达式,其中包括构造函数的调用。

构造函数的函数指针不存在,因为你无法获取构造函数的地址,就这么简单。

即使您可以以某种方式找出构造函数的损坏名称,并从 DLL 获取该构造函数的入口点,您也不应该尝试调用它。你不应该这样做。构造函数只能由语言调用。

这是因为构造函数假设内存已分配,并继续初始化该内存。该语言会处理这一点,但直接调用构造函数则不会。构造函数期望将未初始化的

this
传递给它,但您没有分配任何内存,也没有将任何内容传递给构造函数。结果正如预期的那样:崩溃。 (想想看:构造函数不能在内部分配内存,因为如果对象是在堆栈上初始化的,那么它会如何工作?)

您可以使用工厂方法让您的 DLL 工作。工厂方法是一个公共静态方法,它执行

new ClassA()
并返回结果。然后,从DLL中获取工厂方法的地址,并调用它。

© www.soinside.com 2019 - 2024. All rights reserved.