In C++, property means a private field with a getter and a setter method. Unlike C# and other languages, it is part of the language where it is set or accessed just like a field. In C++ never had the notion of the way C# address gets or set of property field(s).
However, in MSVC, Clang a property extension has been added to give a notion of get / set of property. How it looks like? Let's have a small code:
#include <iostream>
#include <string>
using std::cout;
using std::string;
class Animal
{
string sName_;
public:
string getName() const { return sName_; }
void setName(const string &asName)
{
sName_ = asName;
}
public:
__declspec(property(get = getName, put = setName)) string sName;
};
int main()
{
Animal aObj;
// Set animal name
aObj.sName = "Cat";
cout << "The animal is: " << aObj.sName << "\n";
}
The __declspec extension uses the get and set methods, and these two methods have to be public.
One can argue the usage of properties can also be done through getter and setter methods. Then why to use __declspec properties. This can help us to detect an event on property change. This is nicely shown by Dmitri Nesteruk in his youtube video. However, the following code snippet is showing same along with some modifications (Compiles in MSVC 2022):
#include <iostream>
#include <string>
#include <boost/signals2/signal.hpp>
using std::cout;
using std::string;
using boost::signals2::signal;
template<typename T>
class INotifyPropertyChange
{
public:
signal<void(T*, string, string)> PropertyChanged;
};
class Animal : public INotifyPropertyChange<Animal>
{
string sName_;
public:
string getName() const { return sName_; }
void setName(const string &asName)
{
if (asName == sName_) return;
if (sName_.empty())
{
sName_ = asName;
return;
}
string localName = sName_;
sName_ = asName;
PropertyChanged(this, localName, asName);
}
public:
__declspec(property(get = getName, put = setName)) string sName;
};
int main()
{
Animal aObj;
boost::signals2::connection aConnObj = aObj.PropertyChanged.connect([](Animal* pAnimal, string aOldName, string aNewName)
{
cout << "Animal name has changed from: " << aOldName << " to " << aNewName << "!\n";
});
aObj.sName = "Cat";
aObj.sName = "Dog";
aObj.sName = "Horse";
aConnObj.disconnect(); // Once disconnected no more notification
// gets generated for property change
aObj.sName = "Squirrel";
}
Output:
Comments