C++库制作,隐藏在标头中没有友元的析构函数/构造函数
C++ library making, hiding destructor/constructor without friend in header
我必须创建一个共享库,现在我面临以下问题。(MSVC2015)。我想像 A 类一样隐藏构造函数/析构函数,并且我有一个像 B 这样的"工厂"类。
class A {
public:
private:
A() {};
~A() {};
friend class B;
};
class B {
public:
B() {};
~B() {};
A * Create() { return new A(); };
};
因此,我编译这两个类以创建 .lib 和.dll。我的问题是,如果我给用户包含类 A 的定义以及 .lib 和 .dll 的头文件,但从此标头中删除行友元类 B,那么它会是一个有效的解决方案吗?换句话说:"友元类"是仅在编译时需要,还是在运行时也需要?
感谢您的帮助!
如果您使用好友行编译它,然后删除好友行,则用户始终可以再次添加它。您的用户还可以将函数从专用更改为公共。
如果库导出A::A()
的实现是一个不同的问题,并且在由 declspec(dllexport/import)
属性确定的窗口下,因此独立于私有/公共,它可能可供用户使用,也可能不可用。从我目前所看到的情况来看,公共、私有和友元声明对编译的 dll 没有影响,使用成员指针,您甚至可以在不编译 dll 的情况下访问私有成员。但是在这一点上没有保证。
真正的问题是:你为什么要这样做?
如果你在标头中声明这个构造函数是私有的,只能通过B
访问,提供一个B
的工厂函数,并且(希望)在你的文档中声明用户应该使用这个工厂,那么你已经做了一切合理的事情来阻止用户使用这个类。如果他仍然这样做,那就不再是你的错了。
编辑:(接受挑战)
我刚刚用MSVC 2015编译了以下.dll:
//class.cpp
#include "class.h"
void bar(C & c)
{
c.privatePrint();
}
//class.h
#pragma once
#include <string>
#include <iostream>
class C {
private:
std::string str;
C() :str("foo") {}
void print() {
std::cout << str << std::endl;
}
void privatePrint() {
std::cout << "private " << str << std::endl;
}
friend _declspec(dllexport) void bar(C& c);
};
_declspec(dllexport) void bar(C& c);
并将其加载到以下.exe:
//main.cpp
#include <iostream>
#include "class.h"
#pragma comment(lib,"../Debug/lib.lib")
int main(){
C c;
bar(c);
c.print();
}
//class.h
class C {
public:
std::string str;
C() :str("foo") {}
void print() {
std::cout << str << std::endl;
}
};
_declspec(dllimport) void bar(C& c);
输出:
private foo
foo
所以我们学到的是:这里的构造函数是在类定义中定义的,所以即使没有_declspec(dllexport/import),可执行文件也可以访问它。事实上,我们可以将私有更改为公共,并可以访问构造函数。成员函数print()
也是如此。
尽管我不仅省略了可执行文件标头中 bar()
的 fried 声明,而且还省略了bar()
使用的完整函数定义,但 bar 打印字符串没有问题 - 仅仅是因为 bar()
的代码已经在.dll中编译。
因此,很明显,一个类完全由其成员变量及其布局定义,函数和访问说明符都不需要相同。但是,我并没有说明这符合标准,保证有效或应该完全完成
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- C++中的基元类型有析构函数吗?
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- 什么是带有友元说明符的析构函数
- 为具有许多友元函数c++的模板类(2d动态)创建析构函数
- C++库制作,隐藏在标头中没有友元的析构函数/构造函数
- C++-在基元上运行析构函数
- 基元类型动态分配数组的析构函数
- n元树结构的析构函数
- 用于基元和复杂数据类型的C++模板析构函数