I would like to initialise my class const member in the constructor from std::istream:
class MyClass {
private: const int dataMember;
public: MyClass(std::istream& is) { /* read into datamember }
}
I want to use >> operator of istream instance to fill in my dataMember but my dataMember is const. Is there any way in C++ to do that?
Sure, just wrap it in a function:
MyClass(std::istream& is) : dataMember{readInt(is)}{}
You can handle input errors by throwing from your helper function.
If you really want to do it without a helper function, you can force it with an istream_iterator:
MyClass(std::istream& is) : dataMember{*std::istream_iterator<int>(is)}{}
However, this will lead to somewhat wacky error handling. The error handling can be done via std::istream::exceptions, but the caller would have to remember to enable them. Otherwise, a failing read operation will invoke UB.
I prefer the helper function for that error handling reason. (Especially as it took me three iterations to get it right and I advocated UB in one.)
You can create a function that takes in a stream and returns an object. This function extracts the data from the stream and puts it in the constructor.
static MyClass fromIStream(std::istream& is) {
int datamember;
is >> datamember;
return MyClass(datamember);
}
Related
In the header, I have
class CSomeClass
{
const GUID m_guid;
public:
CSomeClass();
///...
}
And in the source file
CSomeClass::CSomeClass()
, m_guid(
[]() {
GUID g;
::CoCreateGuid(&g);
return g;
}()
)
{
}
As you know Guids can be used as identifications not meant to be changed. Given the ::CocreateGuid() function provides what I want as an output parameter, instead of returning it, I cannot use directly a simple call to the function for initializing the m_guid member field, that is constant.
So, a consequence of its constness, is that it must be initialized before the opening bracket in initializer list, and therefore not be simply assigned with a call to ::CocreateGuid() in the constructor body.
Is there a simpler way to initialize it than this lambda expression?
When the lambda expression is correct, I would use a helper function for that:
GUID create_guid()
{
GUID g;
::CoCreateGuid(&g);
return g;
}
CSomeClass::CSomeClass() : m_guid(create_guid()) {}
In addition, create_guid() has a meaning by itself and could be reused (even if making it a implementation detail is possible/correct).
You should consider wrapping the GUID in its own class:
class CGUID
{
public:
CGUID()
{
CoCreateGuid(m_guid);
}
const GUID& guid() const { return m_guid; }
// Maybe some useful functions:
bool operator==(const CGUID&) const;
private:
GUID m_guid;
};
Now you can use the above as a member:
class CSomeClass
{
const CGUID m_guid;
...
Here we abstract your pattern:
template<class A>
A co_make( HRESULT(*f)(A*) {
A a;
HRESULT hr = f(&a);
Assert(SUCCEEDED(hr));
if (!SUCCEEDED(hr))
throw hr;
return a;
}
CSomeClass::CSomeClass()
m_guid(
co_make(&::CoCreateGuid)
)
{}
where we detect failure and assert then throw if that is the case.
I'm not sure this is simpler.
Really, write a GUID make_guid() function, stick it in some header, and call it.
Your proposal is the simplest way to initialize the constant instance member.
Don't get scared of lambdas, as a matter of fact, in general it is a new style recommendation to use lambdas for complex initializations of constants and references because they share the property of only being initialized at the point of declaration (or instance member initialization in the initializer list).
Furthermore, your code triggers the "named return value optimization" and there is no copy construction at the return from the lambda.
The interface to CoCreateGuid is deficient because it requires an output argument.
If you insist on not using the lambda, I think the next most practical alternative is to, in the constructor body, de-constify using const_cast to pass it to CoCreateGuid.
Mind you that one you enter the body of a constructor the language considers all individual members to have been properly initialized, and will invoke destructors for them should an exception happens, this makes a very big difference whether something is initialized in the initializer list or left with a binary pattern of garbage.
Finally, unfortunately you can't just call CoCreateGuid with a de-constified reference to m_guid in the lambda, because the lambda will still return a value and that will overwrite the member. It is essentially the same as what you already wrote (with the exception of the default constructor of g)
It would be simpler if you declare m_guid as a mutable instance member as opposed to const. The difference is that mutable are like a const for users of a class but a perfectly fine lvalue within the class
Another question from reading "Accelerated C++" by Andrew Koenig and Barbara E. Moo, and I'm at the chapter about constructors (5.1), using the example as before.
They write
we'll want to define two constructors: the first constructor takes no arguments and creates an empty Student_info object; the second takes a reference to an input stream and initializes the object by reading a student record from that stream.
leading to the example of using Student_info::Student_info(istream& is) {read(is);} as the second constructor which
delegates the real work to the read function. [...] read immediately gives these variables new values.
The Student_info class is
class Student_info {
public:
std::string name() const (return n;}
bool valid() const {return !homework.empty();}
std::istream& read(std::istream&);
double grade() const;
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
Since read is already defined as a function under the Student_info class, why is there a need to use a second constructor - isn't this double work? Why not just use the default constructor, and then the function since both are already defined?
It isn't double work on the contrary it simplifies the object initialization for the caller who instantiates the class
If you create the class with a single constructor every time you have to do
std::istream is = std::cin;
Student_info si();
si.read(is);
// si.foo();
// si.bar();
// si.baz();
Maybe some other operations can be added that can be done in constructor. So you don't have to write them again when you need to instantiate the class. If you create 10 instances you will have to write
( 10 -1 = ) 9 more lines and this isn't a good approach for OOP
Student_info::Student_info(istream& is)
{
read(is);
//foo();
//bar();
//baz();
}
But when you define two constructors like above, you can use the class like
std::istream is = std::cin;
Student_info si(is);
One of the main goals of OOP is writing reusable and not self repeating code and another goal is seperation of concerns. In many cases person who instantiates the object doesn't need to know implementation details of the class.
On your example read function can be private when its called inside constructor. This reaches us another concept of OOP Encapsulation
Finally this isn't double work and its a good approach for software design
My question is since read is already defined as a function under the Student_info class, why is there a need to use a second constructor - isn't this double work?
The second constructor takes an argument from the caller and passes it on to the read function. This allows you to directly instantiate a Student_info with an std::istream.
std::istream is = ....;
Student_info si(is); // internally calls read(is)
as opposed to
std::istream is = ....;
Student_info si;
si.read(is); // how could we use is if this call isn't made? Now we have to read some docs...
Why not just use the default constructor, and then the function since both are already defined?
Because it is better to construct objects such that they are in a coherent, useful state, rather than construct them first and then initialize them. This means users of the objects do not have to worry about whether the thing can be used or must first be initialized. For example, this function takes a reference to a Student_info:
void foo(const Student_into& si)
{
// we want to use si in a way that might require that it has been
// initialized with an istream
si.doSomethingInvolvingInputStream(); // Wait, what if the stream hasn't been read in?
// Now we need a means to check that!
}
Ideally, foo should not have to worry about the object has been "initialized" or made valid.
I create a class like this
class myClass {
public:
int addMeOne;
void Invoked() { .... }
};
I created an object of it and used to send it to all other modules of my program by reference . Everyone used to increment the addMeOne variable by 1 . some even used to add twice but that’s not the point .
With this , now I want whenever someone alters addMeOne , my function Invoked() should get called .
Please note that the right strategy would have been that I should have allowed addMeOne to be exposed outside by some function and inside that function I could call Invoked . However , the interface cannot be altered now since this is now exposed to the all others and should not be modified. How can I correct this . ?
You have to make a method that would assign the value to the addMeOne variable, this is known as a setter method, and make the variable itself private.
There is no way to trigger a function upon changing an integer variable, I believe.
One alternative which would change the interface, but would not require changing the code outside is to define a class that would mimic the behavior of an integer, i.e. implement operator++ etc., and change addMeOne to this type.
You needv to read up on encapsulation. Without providing a locked down getter / setter interface to addMeOn there is no way to guarantee control over its use.
Don't be afraid to change the interface. It will not be a big task for anyone using it to change and they should be clear that what you are doing in changing it is to provide value for their benefit.
Should you preserve the ABI of this class, or just the syntax that its clients use?
If you can change the type of addMeOne, preserving the ability to write addMeOne++ etc, you can define a class and the relevant operators for it - then make addMeOne to be an instance of this class. Certainly, now addMeOne operators can do anything -- including invocations of some MyClass member functions.
Psuedo-code:
class Proxy
{
public:
Proxy(YourClass *parent) : parent_(parent), value_(0)
{}
void operator++()
{
++value_;
// doAnything with parent_
}
// accessors, cast operators etc...
private:
YourClass *parent_;
int value_;
};
class YourClass
{
public:
YourClass() : addMeOne(this)
{}
Proxy addMeOne;
};
Really, it's probably worth telling all clients to use a method instead of a public variable. You either need to change the class, the clients or both.
There's no way around it. Do it again and do it right. Take the hit.
There are tricks: Once you expose a member variable one thing that you can do is to replace int addMeOne with some other variable with the same name but a different type. countedint addMeOne. The countedint class you would have to write such that it behaves like an int but that the assignment, incrementation and so on also counts the number of times they have been used. For example
countedint & operator ++(){
m_value++;
m_number_of_uses++;
return *this;
}
countedint & operator --(){
m_value--;
m_number_of_uses++;
return *this;
}
You would probably also need to have a cast operator to int and you could count the number of uses there too.
Use can turn addMeOne into a proxy.
class myClass
{
class addMeOneProxy
{
public:
addMeOneProxy(myClass &s) : parent(s) {}
// This gets called whenever something tries to use the addMeOne
// member variable as an integer.
operator int() const
{
return parent.addMeOne;
}
// This gets called whenever something assigns a value to addMeOne.
int operator=(int val)
{
parent.Invoked();
return val;
}
// You could also implement an operator++ or whatever else you need.
private:
myClass &parent;
};
public:
void Invoked();
addMeOneProxy addMeOne;
};
Of course, if you decide to make Invoked() private at some point, you will need to make myClass a friend class of addMeOneProxy so that addMeOneProxy can call the Invoked member function.
I certainly concur with the other commenters that you should really have getter and setter functions for this, but I also understand that developers often have limited power to control and change the world they live in. So, the proxy is how you can do it if you aren't able or allowed to change the world.
I have looked at this thread on singleton class implementation, but not clear on how to use it in practice. To make the context more concrete, say I have a input stream std::istream instance that many different class need to access, but instead of passing it in for each class constructor, I am thinking of using a singleton class Connection to wrap this info. So a client can just call:
Connection.getInstance().get_input_stream();
My questions are two fold: (1) is this a proper use of singleton class (2) on implementing this, I have tried something like this:
class Connection {
public:
static Connection& getInstance() {
static Connection instance; // Guaranteed to be destroyed
return instance;
}
std::istream& get_istream() {
return is;
}
void set_istream(std::istream & stream) {
is = stream;
}
private:
std::istream& is;
}
First this code doesn't compile for some reason. Second it feels awkward that you have to call set_istream() before it is usable. Is there a better way to get this done? Thanks.
EDIT: Apparently, trying to assign a reference is my silly doing, as many of you pointed out. The second part is how to pass in stream information into singleton - it seems not worth it, which suggests this might be a wrong case for using it. thanks you all for your answers.
A reference can't be modified after creation, so to "set" the istream, you'd have to pass it to the ctor:
class Connection {
/* ... */
Connection(std::istream & stream) : is(stream) {}
private:
std::istream& is;
}
That raises a problem, however, of how you pass the correct stream to the ctor when you're creating a static instance -- and the answer to that is that it's non-trivial (at best). You could use a pointer instead of a reference, so you can create an object and point it at an actual stream later, but at that point you're basically asking for trouble (requiring two-stage initialization).
Ultimately, it's just not worth it. My advice would be against using singleton in this case at all. It looks like it's adding quite a bit of work, and providing little (if anything) in return.
Quite a few people are starting to advise against using singletons at all, at least in C++, and quite frankly, I tend to agree most of the time. This kind of situation is why -- you usually end up with little in return for the work you do on it.
I've always been told to avoid singletons, so there's two parts to this:
class Connection {
public:
static std::istream& getInstance() {
assert(is);
return *is;
}
static void set_istream(std::istream & stream) {
is = &stream;
}
private:
static std::istream* is;
}
std::istream* Connection::is = NULL;
int main() {
Connection::set_istream(std::cin);
Connection::getInstance() << "moomoomoo\n";
}
Note I made the stream static, a pointer, and global (so it's actually a singleton. Your code.... wasn't. There's no reason to have that many references laying around, and if you have is = blah where is is a reference, that does not reseat the reference. It would copy the right to the left, which for streams, doesn't make sense and wouldn't even compile.
Of course, singletons are bad. Use globals, or non-singletons. (This is a global, which is only creatable once)
//params are ignored after first call
template<typename... Ts>
std::istream& Connection(Ts... Us) {
static std::ifstream c(std::forward<Ts>(Us)...);
return c;
}
int main() {
//construct and use
Connect("input.txt") << "thing" << std::endl;
Connect() << "stuff";
Connect("this is ignored") << "IM A COW STOP SAYING IM A DUCK";
}
It doesn't compile for two reasons. First you have a very minor problem with the calling syntax. Fix it like this:
Connection::getInstance().get_input_stream();
Second is that you can't assign to a reference, it must be initialized at construction time. Since your constructor is called from the middle of getInstance, that's impractical. Use a pointer instead.
Yes it's awkward to need to call set_istream before your singleton is usable, but that seems unavoidable.
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.