В C ++ вы либо вызываете функцию-член, либо обращаетесь к члену данных.Свойства Python - это, по сути, способ сделать первое с использованием синтаксиса последнего, и в C ++ нет разумного способа сделать это.
Теоретически вы можете взломать что-то вместе с макросом, #define looks_like_data really_a_function()
, но это не такне красивоИли разумно.Единственная необходимая причина для того, чтобы функция выглядела как данные, состоит в том, чтобы поддерживать совместимость со старым вызывающим кодом с того времени, когда он был данными.Но в C ++ это не даст вам двоичной совместимости и даже не даст вам совместимости с исходным кодом, поскольку макрос нарушит вызывающий код, который уже использует имя looks_like_data
для чего-то другого в другом контексте.Так что в этом нет особого смысла.
Другая вещь, которую вы могли бы сделать, - создать фактический элемент данных, который будет действовать как прокси для «логического» типа данных:
struct Proxy {
Foo *foo;
Proxy(Foo *foo) : foo(foo) { }
operator int() const {
// getter code goes here,
// use (const Foo*)foo rather than foo
}
Proxy &operator=(int a) {
// setter code goes here
}
// optionally also implement boilerplate +=, -=, etc.
};
struct Foo {
// optionally
// friend class Proxy;
Proxy looks_like_data;
Foo() : looks_like_data(this) { }
};
Это почти, но не совсем, разумно.Использование неявного преобразования все еще нарушает совместимость с исходным кодом, поскольку существует правило, согласно которому в цепочке может быть только одно пользовательское неявное преобразование, поэтому, если вызывающий объект записал код обратно, когда looks_like_data
действительно был int
, и их код неявно преобразует это int
в Bar
, затем, когда looks_like_data
становится Proxy
, он больше не будет неявно преобразовываться в Bar
, и вы все равно нарушите их код.
Итак, после всего этого вам лучше всего использовать функции получения / установки, если вашему классу действительно нужно что-то, похожее на свойство чтения / записи.