2016-03-02 2 views
0

Мне нужно создать общую библиотеку, и теперь я сталкиваюсь со следующей проблемой. (MSVC2015). Я хочу, чтобы скрыть конструктор/деструктор, как в классе А, и у меня есть класс «фабрика», как В.Создание библиотеки C++, скрытие деструктора/конструктора без друга в заголовке

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 из этого заголовка, то это будет действительное решение? Другими словами: «класс друга» необходим только во время компиляции или он необходим во время выполнения?

Благодарим за помощь!

+0

Что вы пытаетесь сделать? В чем цель фабрики? – SergeyA

+0

Просто для создания A. Но я не хочу, чтобы пользователь допустил следующее: A a; – bjoska

+0

Почему? Почему пользователь не может выполнять «A a»? И второй вопрос: зачем вам нужен отдельный класс для создания? – SergeyA

ответ

-1

Если вы скомпилируете его с помощью строки друга и затем удалите линию друзей, ваш пользователь всегда сможет добавить его снова. Пользователь может также изменить функцию от частного к публичному.

Если реализация A::A() экспортируется вашей библиотекой, это другой вопрос, а под окнами определяется атрибут declspec(dllexport/import), поэтому независимый от частного/общедоступного он может быть доступен пользователю или нет. Из того, что я видел до сих пор, объявления public, private и friend не влияют на скомпилированную dll и используют указатели-члены, вы даже можете получить доступ к частным членам без компиляции dll. Однако никаких гарантий по этому вопросу нет.

Реальный вопрос: зачем вы хотите это делать?
Если вы заявляете в своем заголовке, что этот конструктор является закрытым и только доступным на B, укажите заводскую функцию в B и (надеюсь) укажите в своей документации, что пользователь должен использовать эту фабрику, тогда вы сделали все возможное, чтобы сохранить пользователь может использовать этот класс. Если он все-таки это сделает, это уже не ваша вина.

Edit: (вызов принят)

Я только составил следующий .dll с MSVC 2015:

//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() в исполняемых файлах заголовок , но и полное определение функции используется bar() это не является проблемой для бара, чтобы напечатать строку - просто потому, что код bar() уже составлен в .dll.

Очевидно, что класс полностью определяется его переменными-членами и их компоновкой, ни функции, ни спецификаторы доступа не должны быть одинаковыми.Однако я не утверждаю, что это соответствует стандарту, гарантированно работает или должно быть выполнено вообще

+0

Ну, я бы сделал его приватным, поэтому сам код не будет компилироваться. Конечно, пользователь может изменить его на публичный, но если я начну использовать библиотеку, я не изменю данные заголовки по какой-то причине :) – bjoska

+0

Неверно. Вы не можете изменить определение класса. – SergeyA

+0

@SergeyA: вызов принят, я попробовал. Я честно не ожидал такой свободы. Теперь взглянем на стандарт, если найду что-нибудь ... – Anedar

Смежные вопросы