I have a shared_ptr I'm trying to use in two functions of a class, not sure if I have it working right. The shared object class I'm using might be broken, but it's not my repo so I'm wanting to check if it's my issue on my end.
myHeader.h
#include "otherClass.h"
namespace myheader {
class myClass : {
public:
// Constructor
myClass();
~myClass() = default;
bool incomingMessage();
private:
std::shared_ptr<randomnamespace::OtherClass> otherClass_ = std::make_shared<randomnamespace::OtherClass>();
};
};
myClass.cpp
#include "myHeader.h"
using namespace myheader;
myClass::myClass()
:
otherClass_()
{
otherClass_->setConfiguration(x);
std::cout << "Debug: Initialized";
}
bool myClass::incomingMessage() {
otherClass_->sendData();
std::cout << "Debug: Data sent";
return true;
}
I'm wondering if it seems to be shared correctly?
I've tried running this(compiling works), and the otherClass_->() calls don't work in either place. Have tried testing both individually with the other commented out, and I don't get the Debug print's after the otherClass_-> calls.
You try to initialize otherClass_ twice:
once with a default member initializer:
std::shared_ptr<randomnamespace::OtherClass> otherClass_ = std::make_shared<randomnamespace::OtherClass>();
once with a mem-initializer in the constructor:
myClass::myClass(): otherClass_()
The standard says that when this happens, the default member initializer is ignored and the member is initialized according to the mem-initializer in ctor. Here that means that you initialize otherclass_ to be an empty shared pointer...
You should remove the offending initialization in ctor:
myClass::myClass()
{
otherClass_->init();
std::cout << "Debug: Initialized";
}
Main question
myClass::myClass()
:
otherClass_()
This initializes your member (otherClass_) with nothing from the constructor.
This will override the definition of
std::shared_ptr<randomnamespace::OtherClass> otherClass_ = std::make_shared<randomnamespace::OtherClass>();
where you already have initialized it before correctly.
Solution:
Remove : otherClass_() from the constructor.
Remove the initialization from otherClass_ and use :otherClass_(std::make_shared<randomnamespace::OtherClass>()) to initialize it from the constructor.
Other notes
Remove the colon after class myClass : {.
To implement incomingMessage() you need
bool myClass::incomingMessage() {
Other than that, I don't see that you return otherClass_ anywhere or pass it as a parameter. You don't share it, you only use it. It looks like you can use a unique_ptr.
Related
Imagine I have a C++ class called MyClass.
Imagine that I have no access to the source code of MyClass ... it is contained in a library and I am supplied only the library and the header file for MyClass.
Imagine that the class itself requires environment pre-configuration ... for example ... before the constructor of the class can be called, I need to do some setup. The class is normally meant to be used as follows:
void func() {
doGlobalSetup();
MyClass myInstance(1,2,3);
myInstance.doSomething();
...
}
Now I have the situation where we need to create a global instance of the class such as:
MyClass myInstance(1,2,3);
int main(int argc, char *argv[]) {
doGlobalSetup();
myInstance.doSomething();
}
The problem is that in this story, the instance of MyClass is created before the call to doGlobalSetup(). It is instantiated before main() is called. What I want to do is either defer the creation of myInstance() till later or be able to run doGlobalSetup() somehow before the instantiation of the class.
This is a simplification of the actual story ... so let us assume:
I can't change the internals of MyClass.
There must be an instance variable called myInstance of type MyClass (I can't change the logic to MyClass *pMyInstance).
Many thanks for reading.
Since you've constrained the problem such that new cannot be used, you should be able to create the object as always and copy it to the global instance. For example:
MyClass createMyClass()
{
doGlobalSetup();
return MyClass(1, 2, 3);
}
MyClass myInstance = createMyClass();
int main()
{
myInstance.doSomething();
return 0;
}
Does it suit your needs?
namespace
{
int doStaticGlobalSetup()
{
doGlobalSetup();
return 0;
}
}
MyClass myInstance(doStaticGlobalSetup() + 1,2,3);
int main() {
myInstance.doSomething();
return 0;
}
If you absolutely have to defer any constructor calls until after global initialization is done, and want to be sure that no static order initialization fiasco happens, there is a way: make myInstance a reference to uninitialized block of memory and create object in it using placement new after global initializaton.
#include <iostream>
#include <type_traits>
struct foo
{
foo() { std::cout << "created\n"; }
void meow() { std::cout << "used\n"; }
~foo() { std::cout << "destroyed\n"; }
};
void doGlobalSetup() { std::cout << "Global setup\n"; }
//Actual implementation
namespace {
typename std::aligned_storage<sizeof(foo), alignof(foo)>::type bar;
}
foo& instance = reinterpret_cast<foo&>(bar);
//Allows automatic creation and destruction
struct initializer
{
initializer()
{
if (!initialized)
new (&instance) foo();
initialized = true;
}
~initializer()
{
if(initialized)
instance.~foo();
initialized = false;
}
private:
static bool initialized;
};
bool initializer::initialized = false;
int main()
{
doGlobalSetup();
initializer _;
instance.meow();
}
Use a static variable inside a function.
MyClass &myInstance() {
doGlobalSetup();
static MyClass myInstance(1,2,3);
return myInstance;
}
void func() {
myInstance().doSomething();
}
You probably already got the answer you wanted. But just to cover the whole spectrum: if, for some reason, you want to make sure that other places in the code don't accidentally construct MyClass independently of your global variable--and before the global setup has been made--you need to solve this with linking.
If you're on Linux, you can LD_PRELOAD a shared-object containing just the symbol for MyClass's constructor. In it, you declare the setup function accordingly, and let the dynamic linker do the job for you. Then, inside the constructor, you call the setup function, and then do a dlsym("...", RTLD_NEXT) to get the pointer to the original constructor, and you call it, passing it the arguments you got. Of course, you maintain and check a static flag for whether setup has already been performed.
Again, this is probably overkill for you, but I'm posting it just in case someone needs (and is able to use) this kind of solution.
P.S. This is what you get when you rely on global state! :)
First, bear in mind that given a library init function like doGlobalSetup there is a distinct nonzero chance the library will just not work if you create a global instance.
Otherwise it's super easy to create an initializer with the comma operator:
bool do_my_setup = (doGlobalSetup(), true);
MyClass myInstance(1,2,3);
Within the GCC compiler environment there is a function attribute capability called constructor. This allows us to flag a function definition with the ability for it to be automatically invoked before main is called and, most importantly before any class constructors are invoked.
Referring back to the original problem definition ... if the doGlobalSetup() function is modified from:
void doGlobalSetup() { ... }
to
__attribute__((constructor)) void doGlobalSetup() { ... }
then its invocation will occur before main is called and also before any static class instance constructors are called. The explicit call to this function would also be removed from main() as its work has been performed implicitly.
I am coming from the Java background. I have the following program.
#include <string>
#include <iostream>
class First {
public:
First(int someVal): a(someVal) {
}
int a;
};
class Second {
public:
First first;
Second() { // The other option would be to add default value as ": first(0)"
first = First(123);
}
};
int main()
{
Second second;
std::cout << "hello" << second.first.a << std::endl;
}
In class Second, I wanted to variable first to remain uninitialized until I specifically initialize it in Second()'s constructor. Is there a way to do it? Or am I just left with 2 options?:
Provide a parameter-less constructor.
Initialize it with some default value and later re-assign the required value.
I can't initialize first in the initializer-list with the right value, since the value is obtained after some operation. So, the actual required value for first is available in Second() constructor only.
MY suggestion: Use a function:
private: static int calculate_first(int input) {return input*5;}
explicit Second(int input) : first(calculate_first(input)) {}
Base classes will be initialized in the order they're declared in the class inheritance list, and then members will be initialized in the order that they're listed in the class, so the calculation can depend on non-static member-variables and base classes if they have already been initialized.
Alternatively:
Default constructor, then reassign:
explicit Second(int input) { first = input*5; }
Dummy value, then reassign:
explicit Second(int input) : first(0) { first = input*5; }
Use boost::optional (or std::optional as of C++17):
boost::optional<First> first;
explicit Second(int input) { first = input*5; }
Use the heap:
std::unique_ptr<First> first;
explicit Second(int input) { first.reset(new First(input*5));}
Second(const Second& r) first(new First(*(r->first))) {}
Second& operator=(const Second& r) {first.reset(new First(*(r->first)));}
Placement new:
This is tricky and not suggested
and worse in every way than boost::optional
So sample deliberately missing.
But it is an option.
Initialize first in the member initializer list.
It may help to perform your calculations in a helper function and use a forwarding constructor:
class Second {
public:
Second() : Second(helper_function()) {}
private:
Second(int calc): first(calc) {}
static int helper_function() { return ...; }
First first;
};
This sentence is the core of the problem:
I can't initialize first in the initializer-list with the right value,
since the value is obtained after some operation.
You should know that what you want to do here is not perfect programming style in Java, either. Leaving the field with some default value and then assigning it a bit later after some calculations have been done effectively prevents it from being final, and consequently the class from being immutable.
In any case, your goal must be to push those calculations directly into the initialization of the member, using private helper functions (which may be static):
class Second {
private:
First first;
static int getInitializationData()
{
// complicated calculations go here...
return result_of_calculations;
}
public:
Second() : first(getInitializationData()) {}
};
In my opinion, everything else is just a workaround and will complicate your life in the long run.
You can just do what you said in the comments, or, you can make first a pointer to First and give it memory whenever you like, although i don't recommend this way
One way to separate object lifetimes is to use the heap, make first a pointer and initialize it anytime you like:
class Second {
public:
First* first;
Second() {
first = new First(123);
}
};
of course, you'll probably want to use a smart pointer of some sort rather than a raw pointer.
If you don't code to explicitly initialize a member variable, the default initializer is used to initialize it.
The draft C++ standard has the following about initialization of base classes and member variables:
12.6 Initialization [class.init]
1 When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form (), the object is initialized as specified in 8.5.
And
12.6.1 Explicit initialization [class.expl.init]
1 An object of class type can be initialized with a parenthesized expression-list, where the expression-list is construed as an argument list for a constructor that is called to initialize the object. Alternatively, a single assignment-expression can be specified as an initializer using the = form of initialization. Either direct-initialization semantics or copy-initialization semantics apply; see 8.5.
I am getting no appropriate default constructor available error with the following simple piece of code:
class A
{
public:
const string cs ;
};
void main()
{
A a;
return;
}
If I remove the const from string then code compiles fine. I can not understand why the default constructor is not getting created by compiler? And what is the deal with const string member variable?
I am working on VS2008.
As mentioned in the comments, const variables cannot be left unitialized in C++. There are two ways you can initialize your variable. In both cases, the content of the string can never be modified (as this is what const means).
1) In the class declaration. This method is useful only if you always want this string to have the same value across all of your objects. It is very inflexible and if you find yourself using it you should probably declare the variable as static.
class A
{
const string cs = "value of cs";
};
2) assign it in the constructor, using constructor chaining. This is much more flexible and idiomatic.
class A
{
const string cs;
public:
A() : cs("value of cs")
{
}
};
Note that this can be used with arguments, eg
A(string s) : cs(s) //initializes cs to the value of s
Your error probably arises from the compiler trying to find the second option.
Since C++17 it is legal to have a const member with no initializer -- if that member has a default constructor which initializes itself. void main() is still incorrect though!
So here is some valid code:
#include <string>
struct A { const std::string cs; };
int main()
{
A a;
}
The string a.cs is an empty string which is const.
If using an older compiler you will have to give a redundant initializer for cs.
Why do this C++ program could run successfully even without constructing the class object?
Let's see the code as below:
#include<iostream>
using namespace std;
class Dopey
{
public:
Dopey() {cout << "Dopey\n";}
};
class Bashful
{
public:
Bashful() { cout << "BashFul\n";}
void f() { cout << " f \n";}
int i;
};
class Sneezy
{
public:
Sneezy(int i) {cout << "copy int \n";}
Sneezy(Bashful d) { cout << "copy Bashful\n";}
Sneezy(Bashful* d) {d->f();d->i=100;} //How could this be correct without
// constructing d !!!!!!!!
Sneezy();
};
class Snow_White
{
public:
Snow_White();
Dopey dopey;
Sneezy sneezy;
Bashful bashful;
private:
int mumble;
};
Snow_White::Snow_White() : sneezy(&bashful)
{
mumble = 2048;
}
int main()
{
Snow_White s;
return 0;
}
This program could run successfully , the cout are as below:
Dopey
f
BashFul
see, without constructing bashful,the f() could be invoked, why?
and when i change the function Snow_White::Snow_White() to the below:
Snow_White::Snow_White() : sneezy(bashful)
{
mumble = 2048;
}
it also runs successfully without constructing bashful , the cout are as below:
Dopey
copy Bashful
Bashful
Any interpretation will be appreciated ! THX !
Your program has undefined behaviour because you are accessing bashful before it has been constructed.
Your problem has to do with your initialization list.
bashful is declared after sneezy.
Therefore, in this code:
Snow_White::Snow_White() : sneezy(&bashful)
bashul has not been constructed yet, because according to Snow_White's declaration, sneezy must be constructed first (yes, the order matters). Therefore, the parameter passed in to sneezy's constructor points to an unitialized object. At this point, the reason it works is what chris has linked to. Keep in mind, that although this works, according to the C++ standard the behaviour is undefined and that means you cannot and must not rely on it to work.
However, the real problem is that bashful hasn't been constructed yet.
To fix that, you would need to alter the declaration of your Snow_White class so that bashful comes before sneezy:
class Snow_White
{
public:
Snow_White();
Dopey dopey;
Bashful bashful;
Sneezy sneezy;
private:
int mumble;
};
One way to avoid this kind of thing occuring is to always keep your declarations and initialization lists in alphabetical order.
The other way is to keep your classes small to begin with, so this is never an issue :)
The bashful member is being constructed as is shown by the inclusion of Bashful in the output. It is true that it is not constructed prior to the address of bashful being taken and passed to the other member's constructor.
There are specific rules as to the order in which member are initialized, but the order initialization or use in the constructor initialization list is not one of the factors in those rules.
Below code instantiates a derived singleton object based on environment variable. The compiler errors saying error C2512: 'Dotted' : no appropriate default constructor. I don't understand what the compiler is complaining about.
EDIT:
Fixed issues with implementing the get instance method which requires definition of both the parent and derived class. By separating the class definitions in separate header files and including the same in Singleton.cpp where the instance function is implemented.
Mainfile – 1
#include <iostream>
#include <string>
#include "Singleton.h"
using namespace std;
int main(){
Singleton::instant().print();
cin.get();
}
Singleton.h
#pragma once
#include <iostream>
using std::cout;
class Singleton{
public:
static Singleton & instant();
virtual void print(){cout<<"Singleton";}
protected:
Singleton(){};
private:
static Singleton * instance_;
Singleton(const Singleton & );
void operator=(const Singleton & );
};
Singleton.cpp
#include "Singleton.h"
#include "Dotted.h"
Singleton * Singleton::instance_ = 0;
Singleton & Singleton::instant(){
if (!instance_)
{
char * style = getenv("STYLE");
if (style){
if (strcmp(style,"dotted")==0)
{
instance_ = new Dotted();
return *instance_;
} else{
instance_ = new Singleton();
return *instance_;
}
}
else{
instance_ = new Singleton();
return *instance_;
}
}
return *instance_;
}
Dotted.h
#pragma once
class Dotted;
class Dotted:public Singleton{
public:
friend class Singleton;
void print(){cout<<"Dotted";}
private:
Dotted(){};
};
There are several problems with your code:
You mean to return type Singleton& or const Singleton&. You are currently returning by value, which is attempting to invoke a copy constructor, and no such constructor exists.
Your default constructor in Dotted probably is not available in Singleton. I suggest you make Singleton a friend of Dotted so that it is able to access that constructor. Although not 100% sure on this one.
You forgot to make the function print() virtual, so your override won't manifest itself.
You have put "friend" in the wrong place; you need to declare Singleton a friend of Dotted in Dotted, not within Singleton.
You should not make your definition of Singleton::instant inline as it needs to construct an instance of Dotted and, in order to do that, it needs to see Dotted's definition. So you should move that to a source file where it is able to see both Dotted and Singleton's complete definitions, respectively.
You need to put Singleton* Singleton::instance_ = 0; in a source file somewhere.
You are missing an else clause in your if(!style) section; currently, if the STYLE environment variable is set, but isn't set to "dotted", then you end up returning a null singleton.
In addition to the above, I strongly advise you to avoid environment variables and singletons. Both of them are examples of "shared mutable state" and can lead to a whole lot of messiness. Singletons, though they have appeared in "design pattern" books for quite some time, are now being understood to be design anti-patterns. It is a much more flexible approach to have an interface that you pass around and simply happen to instantiate once rather than bake in the fact that it exists once into its API.
For example, for your particular case, I would suggest something like the following:
class Printer
{
public:
virtual ~Printer(){}
virtual void print()const = 0
};
class StringPrinter : public Printer
{
public:
StringPrinter() : _str("") {}
StringPrinter(const std::string& str) : _str(str) {}
StringPrinter(const StringPrinter& o) : _str(o._str) {}
virtual ~StringPrinter(){}
virtual void print()const{ std::cout << _str << std::endl; }
StringPrinter& operator=(const StringPrinter& o){ _str = o._str; return *this;}
private:
std::string _str;
};
Then, in any class where you previously used Singleton, simply take a const Printer& object. And print to that object. Elsewhere, you can conditionally construct a StringPrinter("Singleton") or StringPrinter("dotted"). Or possibly some other instance of that interface, although I would suggest using QSettings or some sort of configuration file in place of environment variables, or at least use MYAPPLICATIONNAME_STYLE instead of just STYLE; in other words, if you are going to go the environment variable route, at least qualify its name.
It is not a great error message. The problem is that the compiler cannot generate code for the constructor call, it hasn't yet seen the definition of the Dotted class. C++ compilers are still single-pass compilers. You cannot write the method inline, you have to move it.
class Singleton {
public:
static Singleton & instant();
// etc..
};
class Dotted : public Singleton {
// etc..
};
// Now it works:
Singleton & Singleton::instant() {
// etc..
}
I don't see how this can work. At this point:
instance_ = new Dotted();
Dotted is an incomplete type. With g++ 4.4.1 I get:
error: invalid use of incomplete type 'struct Dotted'
Which compiler are you using?
The first error I'm getting is: strcmp not declared. Hint: it's in the <cstring> (≈ <string.h>) header.
After that the next error is:
instance_ = new Dotted();
"Invalid use of incomplete type."
If you use forward declarations, you must separate the declarations and implementations, so you can do things that require complete types after they are defined.