struct or class and what about public data? - c++

When it comes to creating classes I've been told NO public data members. That's fine and I understand why but here's my issue. I've got a struct that I am using in a class (Linear linked list). I'd really like to initialize one of the struct fields (an array) to NULL so that I can check that the client is passing me valid structs, not uninitalized one's that are full of garbage values. I realize c++ won't let me set a default value in the struct declaration, so how do I protect from the client giving me garbage?
struct task {
char *description;
char *name;
float time_remaining;
float time_spent;
};
Then in my class I'm trying to do something like:
//I am making a copy of "to_add" and storing it in the LLL
int list::add_to_list(const task & to_add)
{ /.../ }
I don't want the user adding a bunch of uninitialized "task's" to the linked list... What to do? When I turned that struct into a class and moved the data members to private I had a TON of issues trying to access the data members to make copies of them. I was very careful not to do anything to effect the value of the var's but I couldn't get away from the compiler giving me errors about "error: passing ‘const task’ as ‘this’ argument of ‘char* task::get_comp_name()’ discards qualifiers [-fpermissive]" ("get_comp_name") was one of the getter's that I was sure wasn't editing any values, just passing me a copy) Please help me before I shoot myself. In the face.

In C++ a struct and a class are the same except for access control. So the struct's default access to members and inheritance is public, whereas the class' one is private. So you can give your struct a defult constructor and others to initialize it.
struct task {
task() : desctiption(0), name(0), time_remaining(0.), time_spent(0.) {}
char *description;
char *name;
float time_remaining;
float time_spent;
};
One side-effect of adding a constructor is that the struct isn't an aggregate anymore. This may or may not be an issue for you.
In C++11, you are also able to initialize members at the point of declaration:
struct task {
char *description{nullptr};
char *name{nullptr};
float time_remaining{0};
float time_spent{0};
};
This in-place initialization accepts type x = y syntax too, and argument-less {} initialization results in value initialization, which results in zero initialization for primitive types, so the arguments in the example could have been omitted.

There are several issues at hand here.
Public or not Public ?
Public attributes can seem handy, but they usually come back to bite you when you least expect it. I already suspect an issue with the time_remaining and time_spent: I suppose that both are modified quite at the same moment, aren't they ?
By default, variable attributes should be private, so that the class may enforce invariants such as time_remaining + time_spent is a constant throughout the lifetime of the task.
It is fine for constant attributes to be public, their role in invariants is settled once and for all in the constructor anyway.
But the weird errors message ?
This is because you lack a good tutorial or book. The problem at hand is quite simple: it is a const-ness related issue.
A const object may only be passed by const-reference or value to functions/methods and only const methods may be called on it. In your case, the proper declaration of the name() method should have a const qualifier after the method name.
Putting it altogether
And throwing in std::string because it's so much easier to manipulate.
class Task {
public:
Task(): time_remaining(0), time_spent(0) {}
Task(std::string name, std::string desc, float duration):
_name(name), _desc(desc), _time_remaining(duration), _time_spent(0) {}
// Accessors
std::string const& name() const { return _name; }
std::string const& description() const { return _desc; }
float time_remaining() const { return _time_remaining; }
float time_spent() const { return _time_spent; }
// Modifiers
void spend(float duration) {
_time_remaining -= duration;
_time_spent += duration;
}
private:
std::string _name, _desc;
float _time_remaining, _time_spent;
}; // class Task
Note: it could probably be beneficial to check that the duration passed to the spend method is not superior to the _time_remaining attribute, otherwise you spend more than you have...

Implement a constructor for the struct:
struct task {
task() : description(0), name(0), time_remaining(0), time_spent(0) {}
char *description;
char *name;
float time_remaining;
float time_spent;
};
The only difference between a class and a struct in C++ is the default accessibility of it's members.

Related

const object or private/const data members (variables) in C++?

We know that const object members cannot be modified once declared but what is the real use of them? We can individually declare variables to be const inside the class or declare them private.
If there is any other significance of const object in C++, then please mention that too.
To answer your question literally:
If you make members of a class const, that applies to every instance of the class, but only to the members that you made const.
If you make an object const, that applies to a single instance of that class, but it does apply to all members of that instance.
const is one of the most elementary subjects in C++, in my opinion. Something that is way too often overlooked.
Generally const has three use cases:
Allowing the compiler to optimize more aggressively
Allowing the compiler to point out our mistakes when we accidentally try to change a const value
Convey intend by specifying that we do not want an object changed
In the case of a const member of a class, we force the object to be initialized during instantiation of the class. Preventing us from accidentally changing it's value in member functions. Which is the big difference to just using a private member variable. We still can accidentally change a private member variable anywhere inside the class.
One of the most useful ways to use const is with parameters:
This can allow major optimization for the compiler, for various reasons that are out of scope of this answer.
And in the case of const references, the compiler can prevent you from accidentally changing the value of that reference.
Most importantly, it allows you to define the signature of your function in a more clarifying way.
I luckily use this once(so far). And i never thought i would need to use a const in a member variable.
class TypeA {
protected:
DataX const* m_data; //get a pointer to a data that shouldn't be modified even inside the class.
public:
TypeA(DataX const* p){
m_data = p;
}
auto& getData(){ return *m_data; } //will return DataX const&
}
For the private member variables, i think they are best for helper-variables in the current class that are really not part of the object logically. Maybe for caching, temporary holder of some data that should be there for a time duration, a counter for an algorithm, etc. And they are only used and should be used in the current class. You don't want other programmers to use them in the derived class because they have a very special use so you hide them in private.
Another example for const member are for constant values aside for enums. I prefer enum over a variable that takes storage but some programmer prefer following on what they used to however you convinced them not to(maybe i'm wrong, and they are really correct, and maybe in the future for some reason the const in the language changed, and then using const might be better.)
class TypeA {
public:
const int HEY_VALUE = 101;
const int YOH_VALUE = 102;
const int HELP_VALUE = 911;
const float MIN_SOMETHING = 0.01;
static const int HELLO_EARTH = 10;
//...
}
I can't find this specific code of mine, but i think i used & instead of const*. I used it like this.
class TypeA {
protected:
DataX& m_data;
public:
TypeA(DataX& p):m_data(p){ //you can only set this once in the constructor
}
auto& getData(){ return m_data; } //will return DataX const&
}
I really prefer using . instead of -> for personal reasons so I really pushing myself to achieve the syntax i want and i came with these weird solutions. It's fun because I discovered that those weird approaches are still valid and achievable in c++.
Update
If there is any other significance of const object in C++, then please mention that too.
Maybe you can const some filler bytes on specific part of the class.
class TypeA {
protected:
const int HEADER_BYTES = 0x00616263;
int m_data1;
int m_data2;
const uint8_t ANOTHER_FILLER_FOR_SOME_REASON = 0xffffffff; //maybe forcing offset address, or alignment, etc.
int m_anotherData;
}
Generally, const keyword is being used to improve readability of the code you are writing.
However, in some cases const can also allow compiler optimizations. Let's see the following code snippet:
int const i = 1;
fun(&i);
printf("%d\n", i);
Here, trying to modify the variable i would cause an Undefined Behaviour. Therefore, the compiler will assume modification won't be even tried so it will pass the value 1 to the printf function.
Same is valid for const data members.

Proper design of member setters/getters in a C++ class

The usual way of designing setters and getters for a class member is the following
class QNumber
{
public:
void setNumber(unsigned int xNumber){ this->mValue = xNumber; };
unsigned int getNumber(void) const { return this->mValue; };
private:
unsigned int mValue;
}
If the member is another class (e.g. QRational as opposed to unsigned int), then the getter would be better returning a reference, in terms of performance.
So the modified design would be
class QNumber
{
public:
const QRational & value(void) const { return mValue;} // getter
QRational & value(void) { return mValue;} // 'setter'
private:
QRational mValue;
}
My question is - isn't there something potentially wrong with the latter approach? I have not seen it much in other people's code and to me, it seems more elegant than set/get method.
Many thanks,
Daniel
The point of getters and setters is to separate the interface from the implementation. If you return a reference, it has to point somewhere in the implementation. Now if you change the implementation, you'll have to start returning by value instead.
Personally I prefer public nonstatic members when the need for anything else is unlikely. Reference-semantic getters and setters provide the worst of both worlds. (I am working on a proposal to improve them, though.)
In addition to Potatoswatter's answer, please note one more point.
You second design provokes usage in the following form:
QRational& r = number.value();
// or
const QRational& r = number.value();
thus the user retains the reference to your inner object. It will be somewhat more difficult to manage in case your number object can be destroyed or moved while r is still there. This does not even depend on whether the const or non-const method is used.
The first design does not expose such problems.
At least in my opinion, if that member acts like an unsigned int (e.g., allows assignment to/from an unsigned int), and you're really sure this class should support direct manipulation of that member (i.e., it should have a "getter" and "setter" at all), then you should at least make access to it clean, rather than requiring other code to be written around that implementation detail. To avoid that, you should define how the type of this object differs from a plain unsigned int, then implement that behavior in a class that defines that type properly and directly.
class QNumber { // bad name--looks like a Qt class name
unsigned int value;
public:
QNumber(unsigned int value = 0) : value(value) {}
QNumber &operator=(unsigned int val) { value = val; return *this; }
operator unsigned int() { return value; }
};
With this, client code can be readable--instead of ugliness like x.SetNumber(2); or x.SetNumber() = 2; you just use x = 2;. This also avoids all sorts of lifetime issues that arise when you let a client get a pointer or reference to the class' internals (which you should generally avoid).

Is it good practice to not initialize every member in a C++ constructor?

I have a class that has two states, and different members are only applicable in one state or the other.
Which is the better practice:
Option 1: constructor initializes only the members relevant to the first (initial) state
Option 2: initialize every member, even if that means inventing "uninitialized" values for members?
E.g.
class Foo {
public:
enum State { A, B };
// Constructor
// Option 1: Only initialize first state
Foo(int a1) : _state(A), _a1(a1) {}
// ... or ...
// Option 2: initialize every member
Foo(int a1) : _state(A), _a1(a1), b1(-1), b2(-1) {}
State getState() const { return _state; }
// Only applicable if State is A
int getA1() const { return _a1; } // Might also add assert that State is A
// Only applicable if State is B
int getB1() const { return _b1; } // Might also add assert that State is B
int getB2() const { return _b2; } // Might also add assert that State is B
private:
State _state;
int _a1;
int _b1;
int _b2;
};
Reading from an uninitialized variable is undefined behavior, so if you use option 1 and then someone calls getB1() or getB2(), you have undefined behavior.
There is nothing inherently wrong with option 1 as long as you clearly document that calling these getters might invoke undefined behavior and in what circumstances that can happen. This way you are moving the burden of ensuring defined behavior to the consumer of this class.
You could also store flags indicating if they've been initialized and throw an exception if a read is attempted before they are initialized. This way you would get a clearly defined error instead of UB. (You could also use boost::optional<int> here instead, which takes care of providing this extra flag for you.)
Considering all of these points, going with a "dummy" value might be preferred simply because there is no risk of undefined behavior and results in a simpler implementation. (If you do go with a dummy value, make sure you provide a static constant value so that callers can compare to see if the value hasn't been set.)
This might be a case where using a union as a member is applicable. You can use a union structure to save memory space while having an assertion check the state of which union members to use.
struct BMembers {
int _b1;
int _b2;
};
union MyUnion {
int _a1;
BMembers members;
};
class Foo {
public:
enum State { A, B };
Foo(int a1) : _state(A), myUnion._a1(a1) {}
State getState() const { return _state; }
// Only applicable if State is A
int getA1() const { return myUnion._a1; } // Might also add assert that State is A
// Only applicable if State is B
int getB1() const { return myUnion._b1; } // Might also add assert that State is B
int getB2() const { return myUnion._b2; } // Might also add assert that State is B
private:
State _state;
MyUnion myUnion;
};
It's a good practice to initialize everything. Maybe your object has no real value that would count as "uninitialized" and that would break your code.
As a solution, consider using separate classes to define each state. That way you document better what is required for each state, and, depending on the size of your members, can save space by storing only what you need:
class Foo{
public:
enum State{A,B};
virtual State getState() const = 0;
virtual int getA1() const = 0;
virtual int getB1() const = 0;
virtual int getB2() const = 0;
};
class Foo_A : public Foo{
public:
Foo_A(int a1) : _a1(a1) {} // State implicit
State getState() const {return A;}
int getA1() const {return _a1;}
int getB1() const {throw "Bad Call";} // For simplicity. You should use a class derived from std::exception;
int getB2() const {throw "Bad Call";}
private:
int _a1;
};
class Foo_B : public Foo{
public:
Foo_B(int b1, int b2) : _b1(b1), _b2(b2) {}
State getState() const {return B;}
int getA1() const {throw "Bad Call";}
int getB1() const {return _b1;}
int getB2() const {return _b2;}
private:
int _b1;
int _b2;
};
I would way it is good practice to initalise everything.
For a state give those values an invalid one that should not be set
PS: For initialisation list do them in the same order as their declaration.
It depends on your particular situation. Initializing each and every variable at its declaration is a good practise.
In a big program, we may forget to initialize variables, that may result in code dumps.
Later we will want to take extra effort to figure out these initialization issues.
So initializing a variable at its declaration itself is a good coding practise.
For this we use constructor for classes.
In this particular case, the 2nd option is better. What happens otherwise if you call getB1() or getB2(), they return garbage values.
If that is damn sure that it wont get called, its okay with that. But its better initialize them.
Leaving any member uninitialised is a prime opportunity for any function with sufficient access (members, friends, etc) to attempt to access that member before it is initialised. That causes undefined behaviour - usually in code outside the constructor. Since the root cause of the problem (uninitialised in constructor) and the trigger (access) are in different locations in code, that means bugs that are difficult to identify, therefore hard to correct.
Generally, therefore, it is better practice to initialise all members in a constructor.
However, that need not mean "inventing" values for some members. The better practice is to avoid creating an object until all information needed to construct it is available.

Assign to constant variable in a constructor?

In C++ how do I make a variable constant but assign to it in a constructor? The reason I want to do this is because I'm trying to use data driven design by putting all my data into an XML file and then loading that data into variables. The problem is that I can't load the values in a initialization list so I have to do it in the constructor (or elsewhere), but then the variables aren't constant.
Here's an XML file:
<weapons>
<pistol>
<damage>5.0</damage>
...
</pistol>
...
</weapons>
Then I've got a class like:
header
class Weapon
{
public:
Weapon();
const float damage;
};
source
#include "Weapon.h"
Weapon::Weapon()
{
//load damage value into damage variable
}
Because the damage variable is constant I can't do anything with it in the constructor, only in the initializer list, but obviously I can't execute code like reading an XML file in the initializer list. So even though the variable will never change should I just not make it constant or is there a proper way to leave it constant and do what I need?
Use an initializer-list:
#include "Weapon.h"
Weapon::Weapon() : damage(3.4)
{
}
You could have a xml parser, for example:
class WeaponXMLParser
{
public:
WeaponXMLParser(const std::string& filename);
float getDamage();
};
Initialize const member in initializers list:
Weapon::Weapon(const WeaponXMLParser& wxp) : damage(wxp.getDamage())
{
}
The body of the constructor indeed runs too late, your const members already have a value. that comes from the initializer list :
Weapon::Weapon()
: damage(0.0f) // 0.0f is the default value
{
}
In your case, you'd have to get it from the XML file, e.g.
float Weapon::LoadDmgFromXML();
Weapon::Weapon()
: damage(LoadDmgFromXML())
{
}
One approach is to use a "builder" class. So in your case you might have WeaponBuilder with appropriate methods that lets you do this:
WeaponBuilder wb(xmlFilename);
Weapon w(wb);
Then everything will be available in Weapon's constructor, so that you can make appropriate things const.
you must do it in initializer list. And you can provide a function that will determine what damage is and returns it, so you can set your const variable:
class Weapon
{
public:
Weapon():damage(damage_xml()){}
const float damage;
private:
float damage_xml();
};
You could use const_cast and make a non-const reference to the const variable.
float &_damage = const_cast<float&>(damage);
_damage = 12.34;

C++ equivalent for java final member data

First, my latest coding is Java, and I do not want to "write Java in C++".
Here's the deal, I have to create an immutable class. It's fairly simple. The only issue is that getting the initial values is some work. So I cannot simply call initializes to initialize my members.
So what's the best way of creating such a class? And how can I expose my immutable / final properties to the outside world in C++ standards?
here's a sample class:
class Msg {
private:
int _rec_num;
int _seq;
string text;
public:
Msg(const char* buffer) {
// parse the buffer and get our member here...
// ... lots of code
}
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
};
C++ offers some nice mechanisms to make your class immutable. What you must do is:
declare all your public (and maybe protected) methods const
declare (but not define) operator= as private
This will ensure that your objects cannot be modified after they have been created. Now, you can provide access to your now immutable data members anyway you want, using const methods. Your example looks right, provided that you make it const:
int get_rec_num() const { return _rec_num; }
EDIT: Since C++11 you can explicitly delete operator=, rather than just leave it undefined. This explicitly instructs the compiler to not define a default copy assignment operator:
Msg& operator=(const Msg&) = delete;
I'd mark your immutable member as 'const', and assign it a value in your constructor initializer list.
I'd also parse your buffer outside of the class, and pass in the string to the constructor.
Something like this:
class Msg {
private:
int _rec_num;
int _seq;
const std::string text;
public:
Msg(const std::string& str) :
text(str)
{
}
// does this look like proper C++?
int get_rec_num() const { return _rec_num; }
};
// parse the buffer and get our parameter somewhere else
NB:
You should make any member functions that do not change the state of your class internals as 'const'; as this will allow you to call them with const objects.
You should avoid inluding a using std::string in header files; as anyone who includes your header has this 'using' forced upon them.
You're on the right track -- use getters for everything, and without any setters, your class is effectively immutable.
Don't forget some of the corner cases though -- you might want to declare the operator=() method as private and not implement it so someone can't override the object with the default compiler generated assignment operator, etc.
// does this look like proper C++?
int get_rec_num() { return _rec_num; }
You should use
int get_rec_num() const { return _rec_num; }
(see the const which allows to call the member on const objects).
To make a variable immutable you have to use the const key word eg const int _rec_num. Const variables can only be initialised through an initialisation list, which gets called before any code in the constructor. This means that you cannot do any processing in the constructor which sets the const member variables.
You have two ways round this, first you can create another internal class which takes in a buffer and parses it into your variables. Put a const version of this into your MSG class and put this in the initialisation list:
class MsgInner
{
public:
int _rec_num;
Msg(const char* buffer) {
// Your parsing code
}
};
class Msg
{
public:
const MsgInner msg;
Msg(const char* buffer) : msg(buffer)
{ // any other code }
};
This is perhaps not so 'standard', but it's another perspective. Otherwise you can also do it as the other answers have suggested with get methods.
On Finalizers
There is none, you have to emulate it. Either by using a cleanup function or by having all your resources encapsulted in RAII classes. The compiler will place static machinery in your application to call destructors on your RAII classes --i.e., when they go out of scope the resources get released through the destructor.
On Immutability and Initialization
Generally if something is immutable and const-correct the class will have all of its members as const and the only time you get to "write" to them is when the class is initialized. However in your case that might not be possible.
I suggest you gather all your resources and initialize the class (via a non-default constructor with const members) once you have them. The other alternative (which I do not abide) is to have a mutator function that "claims" to be const correct but writes to the const values for a one-time post construction initialization.
First of all, it is possible to initialize the members efficiently and at construction time even if they were declared as const (which is neither necessary nor recommended).
I would still suggest that you split this class into two separate classes (pseudo-code):
// Msg: pure data object; copy constructible but not modifiable.
class Msg
{
public:
Msg(int rec_num, ...)
: rec_num_(rec_num)
...
{}
int rec_num() const
{ return rec_num_; }
...
private:
// prevent copying
Msg& operator=(Msg const&);
private:
int rec_num_;
};
// MsgParser: responsible for parsing the buffer and
// manufacturing Msg's.
class MsgParser
{
public:
static Msg Parse(char const* buffer)
{
... parse ...
return Msg(...);
}
};
// Usage
Msg const msg = MsgParser::Parse(buffer);
This also nicely separates the concerns of holding and parsing the data into separate classes.