LINUX.ORG.RU

Разрешить ТОЛЬКО свой конструктор

 


0

2

Всех с новым годом! Как разрешить создавать объекты только через свой конструктор, например Classname(const int i) ?

Я пробовал:

class Foo {
public:
    Foo(QString &str);
private:
    Foo();
    Foo( const Foo& );
    void operator=( const Foo& );
};

Foo b();

и оно вполне себе разрешает юзать не Foo(QString &str), а мне надо чтобы можно было только

Foo b(string);

Ответ на: комментарий от anonymous

А как это поможет решить задачу? Мне просто надо чтобы при создании объекта класса туда сразу передавался параметр, это обязательное условие.

flareguner
() автор топика

Видимо, у QString есть конструктор по умолчанию? Тогда explicit поможет:

class Foo {
public:
    explicit Foo(QString &str);
private:
    Foo();
    Foo( const Foo& );
    void operator=( const Foo& );
};

Foo b();

quiet_readonly ★★★★
()
Ответ на: комментарий от flareguner

У qstring есть конструктор типа string, наверное. Ну и да - ты подходишь к задаче не с той стороны. :)

anonymous
()
Ответ на: комментарий от flareguner
class Foo {
public:
    explicit Foo(QString &str);
private:
    Foo();
    Foo( const Foo& );
    void operator=( const Foo& );
};

Foo b; // без скобок

Неоднозначность: Foo b() воспринимается как декларация функции.

quiet_readonly ★★★★
()
Ответ на: комментарий от flareguner

Никак - нельзя запретить объявление функции, возвращающей Foo. Даже если Foo нельзя скопировать, т.е. даже если в декларации такой функции непременно возникнет ошибка.

В принципе какой-нибудь clang мог бы выдавать предупреждение в такой ситуации, мол, «для такой функции нельзя написать реализацию, может быть, вы имели ввиду переменную Foo b?» Clang ещё мог бы предложить FixIt, который бы убирал скобочки. Но это так, из разряда мечты — чтобы такое появилось, надо сходит и написать в багтрекер. А я лучше схожу поем.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от flareguner

Можно:

#define b();

Но это так, шутка-юмор. Объяви конструктор с параметом-ссылкой. Типа b(string& VeryImportantParameter)

anonymous
()
Ответ на: комментарий от quiet_readonly

private? Такие конструкторы вне класса использовать нельзя. ЕМНИП это как final в некоторых.

anonymous
()
Ответ на: комментарий от anonymous

Тут нет создания объекта. Это объявление функции.

Foo b();

Reset ★★★★★
()

Код правильный, разрешён только один конструктор, а Foo b(); компилятор воспринимает как extern-функцию вместо создания объекта. Или Foo b; или Foo b{}; на C++11 и получите свою ошибку.

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

спасибо, я до этого почему-то не додумался.

flareguner
() автор топика

Какой код крмпилируется, но не должен?

KblCb ★★★★★
()
Ответ на: комментарий от nanoolinux

Что-то я многовато вчера выпил видимо...

flareguner
() автор топика

C++11:

class VeryStrict
{
public:
    VeryStrict(int a)
    {
    }

    template <typename T>
    VeryStrict(T dummy) = delete;

};



int main(int, char **)
{
    VeryStrict a(42);
    VeryStrict b(42.0); //error: use of deleted function ‘VeryStrict::VeryStrict(T) [with T = double]’
}

C++98:

class VeryStrict
{
public:
    VeryStrict(int a)
    {
    }

private:
    template <typename T>
    VeryStrict(T dummy);
};



int main(int, char **)
{
    VeryStrict a(42);
    VeryStrict b(42.0); // error: ‘VeryStrict::VeryStrict(T) [with T = double]’ is private

}

Pavval ★★★★★
()

Может не понял вопроса, но что мешает оставить только один конструктор - со строковым параметром?

xterro ★★★★★
()

Дефолтный конструктор можно не писать вообще. Он не генерируется если ты создал свой, нетривиальный конструктор.

do0dlez ★★
()

Ещё одна ошибка: operator= должен возвращать Foo&, а не void.

kiverattes ★☆
()
Ответ на: комментарий от quiet_readonly

В принципе какой-нибудь clang мог бы выдавать предупреждение в такой ситуации, мол, «для такой функции нельзя написать реализацию, может быть, вы имели ввиду переменную Foo b?»

Он это и так делает:

source.cpp:16:9: warning: empty parentheses interpreted as a function declaration [-Wvexing-parse]
Foo b();
     ^~
source.cpp:16:9: note: remove parentheses to declare a variable
Foo b();
     ^~
http://liveworkspace.org/code/3qqLX1$0

ГЦЦ так не делает, да.

А майкросовтовский компилятор делает: Warning 4 warning C4930: 'wmain::Foo b(void)': prototyped function not called (was a variable definition intended?)

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Действительно, выдаёт. Не заметил т.к. без -Wall -Wextra запускал. Спасибо.

quiet_readonly ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.