2016-04-03 4 views
-2

мне нужно запретить пользователю вызова регулярных конструкторами в class T «S следующим образом:Использовать новый() в C++ в качестве конструктора

T obj (a, b, c); // Compile-time error 
T* objPtr = new T (a, b, c); // OK 

Можно ли в C++?

+4

Зачем вам это нужно? Также рассмотрите вопрос о возврате 'unique_ptr ', чтобы уменьшить объем утечек ресурсов и улучшить безопасность исключений. – juanchopanza

+5

Вы можете инкапсулировать создание объекта в статический метод или класс фабрики. – soon

+1

Оба способа называют один и тот же конструктор, поэтому вы никогда не будете реализовывать его независимо от того, что вы делаете. – Joe

ответ

2

Вы можете имитировать это поведение своего рода с помощью factory pattern: а friend class используется для создания экземпляров объекта:

class T; 

class TMaker 
{ 
public: 
    static std::unique_ptr<T> MakeT(int a, int b, int c); 
}; 

class T 
{ 
public: 
    void PrintMe() { std::cout << a << ", " << b << ", " << c << std::endl; } 
private: 
    T(int a_, int b_, int c_) : a(a_), b(b_), c(c_) {} 
    int a, b, c; 
    friend class TMaker; 
}; 

std::unique_ptr<T> TMaker::MakeT(int a, int b, int c) 
{ 
    return std::unique_ptr<T>{new T{a, b, c}}; 
} 

Теперь пользователи больше не могут построить свой класс непосредственно:

T v { 1, 2, 3 }; // doesn't work 
T* v = new T{1, 2, 3}; // also doesn't work 

И вместо этого они могут использовать только следующее:

std::unique_ptr<T> t = TMaker::MakeT(1, 2, 3); 

Однако имейте в виду, что у вас может быть только XY problem.

0

Как указал Тас, вам нужно использовать завод. Но я думаю, что простой фабричной функции в самом классе достаточно.

#include <iostream> 
#include <memory> 

template <class C> 
struct creator 
{ 
    template<typename... Args> 
    static std::unique_ptr<C> create(Args&&... args) 
    { return std::unique_ptr<C>(new C(std::forward<Args>(args)...)); } 
}; 

class MyClass : public creator<MyClass> 
{ 
private: 
    friend class creator<MyClass>; 
    MyClass(int) { std::cout << "Created"; } 
}; 

int main() 
{ 
    auto p = MyClass::create(0); 
    return 0; 
} 

Поскольку вы, скорее всего, не хочу повторяться, вы можете создать полезный немного шаблонный Mixin (как я сделал выше). Это избавит вас от необходимости печатать один и тот же код шаблона для каждого класса, который вы делаете. Дополнительным преимуществом является то, что использование шаблона обеспечит согласованный интерфейс и соглашение об именах для всех классов вашего приложения, которые должны вести себя одинаково.
И консистенция хороша в программном обеспечении, как мы все знаем.

0

Сделать деструктор закрытым и предоставить функцию удаления. Это заставит оба ваши заявления работать.

class T 
{ 
public: 
    void PrintMe(); 
    T(int a_, int b_, int c_); 
    void deleteMe() { delete this;} 
private: 
    ~T(){} 
    int a, b, c; 
}; 
Смежные вопросы