мне нужно запретить пользователю вызова регулярных конструкторами в class T
«S следующим образом:Использовать новый() в C++ в качестве конструктора
T obj (a, b, c); // Compile-time error
T* objPtr = new T (a, b, c); // OK
Можно ли в C++?
мне нужно запретить пользователю вызова регулярных конструкторами в class T
«S следующим образом:Использовать новый() в C++ в качестве конструктора
T obj (a, b, c); // Compile-time error
T* objPtr = new T (a, b, c); // OK
Можно ли в C++?
Вы можете имитировать это поведение своего рода с помощью 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.
Как указал Тас, вам нужно использовать завод. Но я думаю, что простой фабричной функции в самом классе достаточно.
#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 (как я сделал выше). Это избавит вас от необходимости печатать один и тот же код шаблона для каждого класса, который вы делаете. Дополнительным преимуществом является то, что использование шаблона обеспечит согласованный интерфейс и соглашение об именах для всех классов вашего приложения, которые должны вести себя одинаково.
И консистенция хороша в программном обеспечении, как мы все знаем.
Сделать деструктор закрытым и предоставить функцию удаления. Это заставит оба ваши заявления работать.
class T
{
public:
void PrintMe();
T(int a_, int b_, int c_);
void deleteMe() { delete this;}
private:
~T(){}
int a, b, c;
};
Зачем вам это нужно? Также рассмотрите вопрос о возврате 'unique_ptr', чтобы уменьшить объем утечек ресурсов и улучшить безопасность исключений. –
juanchopanza
Вы можете инкапсулировать создание объекта в статический метод или класс фабрики. – soon
Оба способа называют один и тот же конструктор, поэтому вы никогда не будете реализовывать его независимо от того, что вы делаете. – Joe