Реализации метода C ++: можно ли не вводить имя класса каждый раз? - PullRequest
0 голосов
/ 09 января 2020

Когда у меня есть класс C ++ MyClass в пространстве имен mynamespace, я реализую его методы как

void mynamespace::MyClass::method() { … }

. Я могу обернуть его в пространство имен, чтобы сократить отдельные определения до

namespace mynamespace {

    void MyClass::method() { ... }

}

Есть ли способ избежать необходимости повторного ввода MyClass::, чтобы я мог копировать все до { в заголовок в качестве прототипа при изменении сигнатуры без необходимости каждый раз удалять MyClass:: ?

Я думал, что "класс - это также пространство имен, может быть, я смогу это сделать"

namespace mynamespace::MyClass {

    void method() { ... }

}

, но это жалуется на то, что я переопределил MyClass как нечто другое. using mynamespace::MyClass; также не сработало (но все равно было бы плохо, потому что как бы я объявил автономную функцию где-нибудь ниже этой строки в этом файле, если бы она работала).

Есть ли решение для этого или оно есть? просто невозможно в C ++?

Ответы [ 3 ]

5 голосов
/ 09 января 2020

Нет, полное имя класса должно присутствовать на любом члене класса, определенном вне определения класса. (И может быть только одно определение класса, которое обычно находится в заголовочном файле.)

Стандарт C ++ прописывает это правило в [class.mfct] / 4 :

Если определение функции-члена лексически выходит за пределы определения класса, имя функции-члена должно быть квалифицировано по имени класса с использованием оператора ​::.

и аналогичным образом в [class.stati c .data] / 2 для stati c членов данных.

Вы можете сократить эту квалификацию, используя макросы препроцессора, но это может серьезно повредить удобочитаемости, и это не обычная практика.

3 голосов
/ 09 января 2020

Идиоматического c способа избежать этого нет. Даже если вы или кто-то еще можете придумать «хак» (например, на основе макросов), это сделает код менее читаемым для всех. Обычный и ожидаемый способ написания C ++ состоит в том, чтобы функции-члены имели предшествующий MyClass:: при определении вне определения класса.

Я бы предложил поискать инструмент, который может обновлять подписи между заголовком и исходным файлом. on command.

Или, как предлагают комментарии, предоставьте определения ваших функций прямо с объявлением внутри определения класса (т.е. предоставьте встроенные определения). Но это имеет свои недостатки.

1 голос
/ 09 января 2020

Используя модули C ++ 20, вы можете реализовать класс в одном файле:

module myproject.mymodule;

namespace mynamespace {
    export struct my_class {
        auto my_method() -> int {
            return 8;
        }
    };
}

Или экспортировать весь фрагмент пространства имен:

export namespace mynamespace {
    struct my_class {
        auto my_method() -> int {
            return 8;
        }
    };

    auto also_exported() -> void {
        // ...
    }
}

Затем вместо включения его Вы можете импортировать этот модуль:

import myproject.mymodule;

auto frob() -> void {
    auto my_instance = mynamespace::my_class{};
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...