so I've been learning C++ for a few weeks now but I'm having a bit of trouble:
Class Tool
{
public:
Tool(const float maxCarried = 1):maxAmountCarried(maxCarried){}
virtual void Use() = 0;
/* ... */
}
Class CuttingTool: public Tool
{
public:
CuttingTool(const float maxCarried):Tool(maxCarried){}
virtual void Use(){ /* ... */ }
/* ... */
}
Class Saw: public CuttingTool
{
public:
Saw(const float maxCarried):CuttingTool(1){}
virtual void Use(){ /* ... */ }
/* ... */
}
Class Scissors: public Fruit
{
public:
Scissors(const float maxCarried):CuttingTool(2){}
virtual void Use(){ /* ... */ }
/* ... */
}
A few things to note:
I'm trying to make a big database of 'Tools'.
I never change the value of 'maxAmountCarried' so I've set it to const.
Memory/performance is important because I have a huge vector of Tools.
The problem lies within the fact that I have to keep writing:
ClassName(const float maxCarried):BaseClass(maxCarried){}
It's really tedious, moreover, I worry that if I were to add a new const value I would have to repeat the process all over again (problem when you have 50 classes inheriting from Food :S).
I feel as though I've designed this poorly. Is there a way to avoid repeating the same line of code over and over again or do I just have to suck it up and deal with it?
Thanks in advance.
If your only concern is the repeating initialization list you could use a macro like this:
#define DEFAULT_CONSTRUCTOR(Child, Parent) Child(float max) : Parent(max) {}
and use it like so:
class Saw : public CuttingTool
{
public:
DEFAULT_CONSTRUCTOR(Saw, CuttingTool) {}
};
You can extend this idea and do something like that:
#define BEGIN_CLASS(Child, Parent) class Child : public Parent { \
public: \
Child(float max) : Parent(max) {}
#define END_CLASS };
and declare your classes:
BEGIN_CLASS(Scissors, Tool)
void cut_through_paper() {} // specific method for scissors
END_CLASS
Note that there is no point of using const float as a parameter since you can't change arguments passed by value anyway. You might however want to use const float& to pass an argument by reference, and that will make sense if size of float is bigger than the size of a pointer in your specific platform.
If you never change you max value, you can make it static and share it between all tool instances:
class Tool
{
protected:
static const float _max;
public:
Tool() {}
};
const float Tool::_max = 0;
If you'd like to be able to change max value only once (say at the begining of your program, you can add a static function:
static void globalMax(float max) { Tool::_max = max; }
and use it where appropriate:
int main() {
Tool::globalMax(5);
...
...
}
Note that you should remove the const from the _max declaration.
Finally, if performance is an issue, you probably need to rethink your design and maybe go with something else (templates maybe?)
Hope that helps!
Related
I am building a matlab MEX function using the matlab c++ data api. My mex function accepts a struct with some fields of varying size, type and name as an input. The exact makeup of this struct could vary and is defined outside the scope of the program, but I know all the possible combinations of the constituent fields ahead of time. We will call this parameter called 'Grid', and Grid is passed to a helper function.
In this helper function, I would like to generate an instance of a derived class where the specific type of derived class will either depend on/correspond to the specific combination of the fields of Grid. The idea is that I can extract the fields of Grid and use them to create the instance of the correct derived class. I would like to achieve this without the need to rewrite my code every time I add a new derived class with a different possible combination of fields. How could I do this? I am open to alternate approaches and strategies as well.
For example, Grid might be defined in the matlab environment like:
Grid = struct('XPSF',X(:),'ZPSF',Z(:),'xe',Trans.ElementPos(:,1)*wvlToM,'TXDelay',TXdelay(:,8));
Then handled by the mex function and passed to the helper function whose definition looks like:
void extractFields(matlab::data::StructArray& Grid);
Currently, Grid can also be composed of a single value in place of XPSF or ZPSF. I anticipate possibly adding other fields to Grid in the future. For each of these possible combinations, I have a derived class that has some unique overridden functions:
class Beamform {
public:
//Constructor
Beamform();
virtual ~Beamform() {}
template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); }
virtual void calcIDXT(...);
};
class bfmPlaneWave : public Beamform
{
public:
double theta;
Eigen::VectorXd xe, XPSF, ZPSF, dTX;
template<typename Derived>
bfmPlaneWave(double& angle, ...);
template<typename Derived>
void calcIDXT(...) override;
};
class bfmXRflMTX : public Beamform {
public:
double theta, zCoord;
Eigen::VectorXd xe, XPSFin, XPSFout, dTX;
template<typename Derived>
bfmXRflMTX(double& angle, ...);
template<typename Derived>
void calcIDXT(...) override;
};
class bfmZRflMTX : public Beamform {
public:
double theta, xCoord;
Eigen::VectorXd xe, ZPSFin, ZPSFout, dTX;
template<typename Derived>
bfmXRflMTX(double& angle, ...);
template<typename Derived>
void calcIDXT(...) override;
};
I would start by declaring a common pattern for construction. Something like this:
class Beamform
{
public:
virtual void calcIDXT(...) = 0;
virtual ~Beamform() = default;
};
class bfmPlaneWave: public Beamform
{
public:
/** Return nullptr if not compatible */
static bfmPlaneWave* fromGrid(matlab::data::StructArray&);
virtual void calcIDXT(...) override;
};
class bfmXRflMTX: public Beamform
{
public:
/** Return nullptr if not compatible */
static bfmXRflMTX* fromGrid(matlab::data::StructArray&);
virtual void calcIDXT(...) override;
};
Then you could have a simple, central factory function that you extend as required:
/**
* Option 1: Use a central dispatch function which can be updated with a
* simple two-liner
*/
std::unique_ptr<Beamform> beamformForGrid(matlab::data::StructArray& Grid)
{
std::unique_ptr<Beamform> rtrn;
if(rtrn.reset(bfmPlaneWave::fromGrid(Grid)), rtrn != nullptr)
return rtrn;
if(rtrn.reset(bfmXRflMTX::fromGrid(Grid)), rtrn != nullptr)
return rtrn;
// insert more here
return rtrn;
}
However, if I understand you correctly, this is something that you don't want. In that case you could use a central registry and global constructors. Global constructors (those for global variables) are run when a DLL is loaded. This is similar to how for example CppUnit registers its unit tests.
class AbstractBeamformFactory
{
public:
virtual ~AbstractBeamformFactory() = default;
/** Return nullptr if not compatible */
virtual Beamform* fromGrid(matlab::data::StructArray&) = 0;
};
/**
* Registers existing factories
*
* Follows the singleton pattern.
* Yes, it is frowned upon, but if it works, it works.
*/
class BeamformRegistry
{
/**
* Protects the list of factories
*
* A bit overkill seeing how neither Matlab nor global constructors are
* particularly multithreaded, but better safe than sorry
*/
mutable std::mutex mutex;
std::vector<AbstractBeamformFactory*> factories;
public:
/**
* Retrieves singleton instance
*
* This isn't a global variable because we need to use it in other
* global constructors and we can't force a specific order between
* global constructors
*/
static BeamformRegistry& globalInstance();
void add(AbstractBeamformFactory* factory)
{
std::lock_guard<std::mutex> lock(mutex);
factories.push_back(factory);
}
void remove(AbstractBeamformFactory* factory)
{
std::lock_guard<std::mutex> lock(mutex);
factories.erase(std::find(factories.begin(), factories.end(), factory));
}
std::unique_ptr<Beamform> beamformForGrid(matlab::data::StructArray& Grid) const
{
std::unique_ptr<Beamform> rtrn;
std::lock_guard<std::mutex> lock(mutex);
for(AbstractBeamformFactory* factory: factories)
if(rtrn.reset(factory->fromGrid(Grid)), rtrn != nullptr)
break;
return rtrn;
}
};
/**
* Implements AbstractBeamformFactory for a specific type of beamformer
*
* Create a global variable of this type in order to add it to the global
* BeamformRegistry
*/
template<class BeamformImplementation>
class BeamformFactory: public AbstractBeamformFactory
{
bool registered;
public:
explicit BeamformFactory(bool registerGlobal=true)
: registered(registerGlobal)
{
/* don't move this to the base class to avoid issues around
* half-initialized objects in the registry
*/
if(registerGlobal)
BeamformRegistry::globalInstance().add(this);
}
virtual ~BeamformFactory()
{
if(registered)
BeamformRegistry::globalInstance().remove(this);
}
virtual Beamform* fromGrid(matlab::data::StructArray& Grid) override
{ return BeamformImplementation::fromGrid(Grid); }
};
/* in CPP files */
BeamformRegistry& BeamformRegistry::globalInstance()
{
static BeamformRegistry instance;
return instance;
}
/*
* Make global variables to add entries to registry.
* These can be scattered across different cpp files
*/
BeamformFactory<bfmPlaneWave> planeWaveFactoryInstance;
BeamformFactory<bfmXRflMTX> XRflMTXFactoryInstance;
Now you can simply call BeamformRegistry::globalInstance().beamformForGrid(Grid) to access all registered beamform implementations and to extend the number of implementations, you just scatter factory instances across your cpp files.
One thing I'm unsure about is how this interacts with MEX. When does Matlab load its extensions? If this only happens in some form of lazy fashion, the global constructors may not execute soon enough. I guess it is worth checking with a few print statements.
Let's say that I have this class in C++:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
}
How can I unit test exampleMethod()? I would like to do something like this:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.example_var;
obj.exampleMethod();
int after_call_value = obj.example_var;
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
But example_var is private.
So, what is the right way to do this unit test? How can I test if a private example_var has changed?
Short answer: Dont do it.
Your test should test against the public interface only. Let me try to explain with some code:
class Adder {
int a,b;
public:
Adder() : a(0),b(0) {}
void set(int x,int y) { a=x;b=y; }
int get() { return a+b; }
};
and a test (assume for a moment we had access to a and b):
void testAdder(){
Adder add;
int a = 1;
int b = 2;
add.set(a,b);
ASSERT_EQUALS(add.a,a);
ASSERT_EQUALS(add.b,b);
ASSERT_EQUALS(add.get(),a+b);
}
Suppose you already distributed the code and someone is using it. He would like to continue using it but complains about too much memory consumption. It is straightforward to fix this issue while keeping the same public interface:
class Adder {
int c;
public:
Adder() : c(0) {}
void set(int x,int y) { c = x+y; }
int get() { return c; }
};
That was easy, but the test will fail :(
Conclusion: Testing private implementation details defeats the purpose of testing, because each time you modify the code it is likely that you also have to "fix" the test.
It is bad approach to test private variable/methods. But if you need there are a lot of options:
You can make Your test class as friend of ExampleClass
You can grab information using moc object
If you want to access example_val, there are one of two things you can do. The first is by making testExampleMethod() a friend method, as follows:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod(); //Now you can use the function as is.
}
On the other hand, you could just add a getter to your ExampleClass to access the variable, such as the following:
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
inline void getExampleVar() const { return example_var; }
}
And then change testExampleMethod() to:
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.getExampleVar();
obj.exampleMethod();
int after_call_value = obj.getExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
I would honestly use the second method, since accessing a class's private variables is generally not recommended.
You just simply implement get function for that private variable you want to get.
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
int GetExampleVar(){
return example_var;
}
}
And call it like
void testExampleMethod(){
ExampleClass obj;
int before_call_value = obj.GetExampleVar();
obj.exampleMethod();
int after_call_value = obj.GetExampleVar();
ASSERT_NOT_EQUALS(before_call_value, after_call_value);
}
Or make testExampleMethod friend function (friend function can access private variables of friend class even if its not its method).
class ExampleClass{
private:
int example_var;
public:
void exampleMethod(){
example_var = other_value; // other value will be always different
}
friend void testExampleMethod();
}
In my opinion first example would be more suitable, but if you cannot modify ExampleClass, you can turn off access control for gcc -- -fno-access-control.
A few options I can think of:
1) Make the test code a friend of the class. That way it can access the private members.
2) Add a getter to the class that's under a #ifdef Testing directive that only gets defined when building the test version (or put public: under that macro and a private: in the #else branch).
3) #define private public when building the test (no, not really).
4) Use gcc's -fno-access-control flag when building the version to test, so that everything is public (if you are using gcc that is).
5) Just give up testing externally from the class and instead add relevant static_asserts/asserts to the class itself to test invariants.
6) Don't. Just stick to testing the public interface.
Hope that helps :-)
i want to understand the behavior of pure virtual functions in derived class when passing to it an argument of same type as (abstract) base class.
to clarify the question, i took the following code from GeeksForGeeks and modified it:
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary(const Employee&) = 0;
{ /* common raise salary code */ }
virtual void promote(const Employee&) = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary(const Employee&)
{ /* Manager specific raise salary code, may contain
increment of manager specific incentives*/ }
virtual void promote(const Employee&)
{ /* Manager specific promote */ }
};
}
Now, how can we get access to the field degree in derived class Manager inorder to update his degree? since the passed argument to raiseSalary(Employee& employee) could be Manager or Engineer
I think there are two ways to handle that problem. Let's start with some really bad solution: using casting. In that case dynamic_cast. You can try to down cast a type. If dynamic_cast isn't able to do that it is going to return a null pointer or throw an exception (depends on wheather you cast a pointer or a value/reference type). But that approach is going to force you to adapt your casts as more Manager, Engineer types are going to come. You might also need to use friend to allow specific classes to access internals of others. friend is not going to be inherited in the hierarchy, so you are going to end up with many friends => broken, broken, broken :(
An alternative would be to use the Visitor Pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Using the visitor pattern you can also make a base no-op visitor and finer grained Visitors to handle specific stuff. Just a small example (with specific visitors without derivation):
namespace example {
class SalaryRaisingVisitor;
class EmployeePromotingVisitor;
class Employee
{
public:
Employee() {}
//don't forget to implement the copy constructor: read more about rule of 3!!!
virtual ~Employee {}
virtual void accept(SalaryRaisingVisitor const&) = 0;
virtual void accept(EmployeePromotingVisitor const&) = 0;
};
class Manager: public Employee {
private:
int degree;
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this, degree);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this, degree);
}
};
class Engineer: public Employee {
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this);
}
};
class SalaryRaisingVisitor
{
void visit(Manager& m, int& degree) //might be const if no internal state changes
{
//...
}
void visit(Engineer& e) //might be const if no internal state changes
{
//...
}
};
}
At the end as you deal with C++, try to avoid virtual functions :) and move everything to static polymorphism :)
You are getting the concept of virtual functions with classes wrong. The class "knows" what it is (via vtable), so you can just write it as class function, not as static global function. Each function inside the class knows all class variables, so you don't have to pass an object of the class.
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary() = 0;
{ /* common raise salary code */ }
virtual void promote() = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary()
{
//the Employed standard code
Employee::raiseSalary(); //This won't compile since you set the virtual function = 0
//Manager specific raise salary code
degree = 0; //this lazy bastards should do real work like coding stuff
}
virtual void promote()
{
Employee::promote(); //employee common code. This won't compile since you set the virtual function = 0
/* Manager specific promote */
degree = degree * 2;
}
};
Employee array[10];
array[0] = Manager(); //create a manager object on the stack
array[1] = Manager(); //create a manager object on the stack
array[0].raiseSalary(); //Only Mananer0 gets raiseSalary
/*the manager object in array[0] uses its virtual function
to the manager raiseSalary function. The Manager RaiseSalary function
in this case calls the base class raiseSalary function explicitly
via Employee::raiseSalary(); */
You should rather structure your code like this:
class Employee
{
virtual void raiseSalary() = 0;
virtual void promote() = 0;
};
class Manager: public Employee
{
virtual void raiseSalary()
{ /* Manager specific raise salary code, may contain... */ }
virtual void promote()
{ /* Manager specific promote */ }
};
int main()
{
Manager bob;
bob.promote(); // <--- Proper method in the Manager class will be called.
// Current instance will always have the right class.
}
In other words you should seek opportunity to pass the specific derived class as the this parameter. Unfortunately this will not work in complex cases when multiple params are needed. But well, this was the idea of the language designers. The perfect language is not developed yet.
I think that you can't and it's the wanted behaviour.
The only way to do this is to cast you argument (which is quite complicated in C++ since you have four different kind of casting). Other solution is to give to any employee a grade attribute.
Alexis.
I have seen multiple public and private keywords in a class definition, like the example below:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
What is the practical use of this (if any)? Is there any situation in which this could be useful?
Is there any situation in which this could be useful?
I can think of a situation where it would be very problematic otherwise:
class myClass
{
public:
void func1(){}
public:
void func2(){}
COORDINATES; // <-- Note the macro here!
private:
int z;
int baz;
};
which, after the expansion of the COORDINATES macro, becomes:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
If multiple private / public keywords weren't allowed, it would be very painful to do it. Although using macros isn't good practice; neither is introducing access modifiers silently for all the members appearing after the macro. Nevertheless, it could be useful for RAD tools generating C++ source code.
I can only guess why you see that in human written classes. My guess is that it is poor coding; the writer probably wanted to express that a chunk of data belongs together and / or wanted to be able to move up and down those chunks within the class definition, together with the corresponding access modifier (private/protected/public).
I'll go one step farther from my comment for this answer, with a snippet of code.
class myClass {
// initializers etc
public:
myClass();
~myClass();
// signal processing
public:
void modifyClass();
private:
float signalValue;
// other class responsibilities
public:
void doWork();
private:
void workHelper();
};
and so on. I wouldn't say this is a solid DESIGN for the class, but it's a good way to show the different capabilities of a class.
Another use is when you want to have a specific destruction order. Lets consider two cases:
Bad case
// Auxiliary class
Class StorageCleaner {
public:
StorageCleaner(ExternalStorage* storage) : storage_(storage);
~StorageCleaner() { storage_->DeleteEverything(); }
private:
ExternalStorage* const storage_; // Not owned
}
// Class with bad declaration order
Class ExternalStorageWrapper {
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
// Other data which should be private
int other_int;
string other_string;
....
};
What happens when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first
destroy other data
Then it will destroy external storage pointed by pointer_to_external_storage_ (because fields are destroyed in reversed declaration order).
Then it will attempt to destroy cleaner_
But cleaner inside its own destructor attempts to manipulate external storage, which has already been destroyed!
Good case
// Class StorageCleaner same as before
...
// Class with better declaration order
Class ExternalStorageWrapper {
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
// Other data which should be private
int other_int;
string other_string;
....
};
What happens in this case when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first destroy other data.
Then it will attempt to destroy cleaner_. Cleaner will DeleteEverything() from storage using storage_ pointer to still existing storage.
Finally, storage gets destroyed through pointer_to_storage_.
I actually had to debug such problem in a company, so although rare, this peculiar case is possible to occur.
One use case I encounter is for the clarity. As shown in the example below, class1 inherits base class which contains a pure virtual function that class1 needs to implement. To indicate that method1 in class1 is coming from some other class class1 inherits from (e.g. base) instead of class1's own function, we use another public to make this point clear:
class base {
public:
virtual void method1() = 0;
}
class class1: base {
public:
myOwnMethod1();
myOwnMethod2();
public: /* base interface */
method1();
Just finished reading those examples. Hopefully this one could contribute on how useful multiple keyword definition is.
We don't quite need to assume much since this is my current problem as of now but consume the following:
class IOHandler {
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Doesn't detect the struct being referenced at which is at below.
private:
typedef struct colorProps // This is the struct that the public function where trying to get referenced at but failed to do so.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
};
The error code.
identifier "_COLOR_OUTPUT" is undefined.
At this point, my intelliSense keep complaining that _COLOR_OUTPUT is undefined within public class scope.
The most probable solution is to put the struct inside public scope instead of private scope.
But I don't want to.
The reason this happens was due to the compiler reads the file from top to bottom. Anything that is declared
that requires reference should be on top and that should resolve the issue. Since I don't want to make things messed up by putting all private class functions and variables
on top. I should just declare another specifier on the top so that any public function requiring some reference might see it ahead.
So the solution is the following: (Is to move all referrable variables and struct on top of the class so that any private and public function argument reference is being recognized.)
class IOHandler {
// Private Class Scope for Variables and Structure
private:
typedef struct colorProps // This is the struct we move at the top for recognizing references.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Now recognizable reference.
private:
... // Any other functions, excerpt.
};
Is there a way in C++ to enforce the use of getters or setters WITHIN the class?
class C{
private:
int x; // should only be Changed by setX();
private:
setX(int i){
(...) // enforce some complicated invariantes
x = i;
};
m(){
x = 5; // should not not allowed
}
}
The only thing that comes to my mind is to put all the super-private members as private variables into an abstract base class with protected getters/setters.
But that doesn't sound like good practice.
Are there any more common ways or conventions to ensure, that everyone uses the setters?
(My purpose:
If the class gets bigger i find it hard to remember what variables carry invariants with them. And currently before setting any variable I search, whether I created a getter or setter (to find out whether i have to consider invariants). But i want to get rid of this unprofessional searching-each-time.)
You can take advantage of composition like this:
class C_int
{
public:
void setX(int i)
{
/* enforce invariants */
x = i;
}
private:
int x;
};
class C
{
pulbic:
void m()
{
x.setX(5);
// x.x = 5; // Won't compile.
}
private:
C_int x;
};
But I find it odd that this is an actual problem for you, IMHO. You're the writer of the C class and its members. You have control over how the x variable is read/written, and x is not part of the public interface of the class. While it is true that other people (e.g. maintainers) can write code that breaks invariants in the future, unit tests should be able to cover those cases.
a) favor accessors throughout your codebase for consistency. then you will more easily spot direct accesses to members. if you need special accessors, then create special methods:
void setFoo(const t_foo& foo) {
assert(foo.isValid());
this->d_foo = foo;
}
void invalidateFoo() {
this->d_foo = t_foo::InvalidFoo();
}
b) to get to an answer: i'll often create an inner class (temporarily in some cases):
class C {
class t_inner {
public:
/* ... */
void setX(int arg) {
/* enforce some complicated invariants... */
this->x = arg;
}
const int& getX() const {
/* ... */
return this->x;
}
private:
int x;
};
public:
/* ... */
private:
/* ... */
void m() {
this->inner().setX(5);
}
private:
t_inner d_inner;
};
The clean answer is No. There is no language feature for that; you can do some variation to achieve it, but that will clutter your code.
In Visual C++, __declspec( property ) can be used to have this feature:
__declspec(property(put=setFunction, get=getFunction)) data-type property-name;
See this article