I am writing the following classes in C++.
class SImage {
...
public:
SImage(char*);
}
class SImageProc {
SImage S;
...
public:
SImageProc(SImage Im) { S = Im; };
}
When compiling I receive this referencing the line where I implement my constructor:
SImageProc.cpp:5:33: error: no matching function for call to 'SImage::SImage()'
I cannot figure out why it is interpreting my parameters as instantions of a class when implementing the SImageProc class.
SImage does not have a default constructor, because you have provided constructor SImage(char*). This means the compiler no longer provides a default one. Something elsewhere in your code requires SImage, causing the error.
You need to provide a default constructor for SImage, or remove the code that requires it. It is not possible to say which one of the solutions is suitable without more details.
My wild guess would be that SImageProc has an SImage data member, and you are not initializing it in the constructor initialization list. This is how you would fix that problem:
SImageProc(SImage Im) : S(Im) {};
The explanation for that is that, by the time you reach a constructor's body, all data members and bases have been initialized. After initialization you can only modify them (in your example, you were assigning to S.) If you do not explicitly initialize data members and bases in the constructor initialization list, they (usually) get default initialized, which in the case of a user defined type means the default constructor is called. This is the source of the error.
Related
I want to declare two objects from two different classes inside my private section of my class. The problem I have is that the second object should take the first object in a constructor. So here is the example of my class private section:
class FactorGraph
{
private:
gtsam::ISAM2Params _parameters();
gtsam::ISAM2 _isam(_parameters);
The _parameters object should be passed as an argument for the _isam object but from my knowledge that will not be possible as C++ does not allow this. Is there a slick way to do so?
Initialize your second object in the constructor (or better both):
FactorGraph::FactorGraph()
: _parameters{}, _isam{_parameters}
{ }
The initialization happens in the same order in which the members are listed in your class (regardless of the order of this list(!), so it's a good idea to keep the same order here, your compiler may even warn you otherwise), which here guarantees that _isam won't get anything uninitialized. (I'm not aware of such guarantees if you just define your objects in your class declaration.)
From the comments, thanks #drescherjm: In your class, just declare your objects without initializers:
class FactorGraph
{
private:
gtsam::ISAM2Params _parameters;
gtsam::ISAM2 _isam;
When you declare them without initializers, they should be initialized in the constructor instead. They do not need to be default-constructible in order to do this, the objects gets initialized only once (in the constructor)
Then if you have more constructors, don't forget to either do that everywhere or forward to this one:
FactorGraph(int) : FactorGraph{}, /* other initializers */ { }
I have confusion after reading from some places.
I'm doing example from this page
let's say there's a class(Book) which has an object(Author) as one of its member. Here's the constructor:
Book::Book(string name, Author author, double price, int qtyInStock)
: name(name), author(author) { **// Must use member initializer list to construct object**
// Call setters to validate price and qtyInStock
setPrice(price);
setQtyInStock(qtyInStock);
}
I tried to declare the object author inside the constructor instead of initializer lisr. It gave me error. no matching function to call Author::Author() --> which is the default constuctor of Author.
After reading from these stackoverflow posts : this1 and this2
What I understand is that, summarizing from those 2:
an object is considered & must be fully initialised when execution enters the body of the constructor
An object has all of its members initialised in the initialisation list. Even if you do not explicitly initialise them there, the compiler will happily do so for you
native types like int or double do have a default constructor
So from all of those above, what I understand is a user defined object/class DOES NOT automatically have DEFAULT CONSTRUCTOR, unlike the primitive types.
That's why it gives error, if I do not use member initializer list (which calls copy constructor) , cause the compiler tries to initialize it using default consturctor which it(user defined class) does not have.
And so possible solutions are: define a default constructor for the class, or use member initializer
AND THEN I read this post on stackoverflow saying that:
"How Many default methods does a class have?" and the answer mentions that It HAS DEFAULT CONSTRUCTOR
1. If it has default consturctor, Why does my first case( the book and author classes) give error?
Also I read from this page, lets say I defined a class Point before, then page wrote:
Point p1; // **Invoke default constructor**
// OR Point p1 = Point(); NOT Point p1();
2. So when we declare like above, does it INVOKE DEFAULT CONSTRUCTOR? Why it does not give an error if so? I thought a class does not have a default constructor?
Appreciate if you can help me to clarify things here, and answer the two questons above (italic)
The full answer is big, and is presented here:
http://en.cppreference.com/w/cpp/language/default_constructor
If you specifically make one, there is always a default constructor. This includes constructors that MAY accept parameters but don't have to - constructors with default parameters and variadic templates can both be default constructors.
If you mark it as = delete then it will never have one.
Otherwise, if no user-provided constructors are present the compiler will try to make one for you except for in certain circumstances (fully listed in the link above in the Deleted implicitly-declared default constructor section)
T has a member of reference type without a default initializer.
T has a const member without user-defined default constructor or a default member initializer (since C++11).
T has a member (without a default member initializer) (since C++11) which has a deleted default constructor, or its default constructor is ambiguous or inaccessible from this constructor.
T has a direct or virtual base which has a deleted default constructor, or it is ambiguous or inaccessible from this constructor.
T has a direct or virtual base which has a deleted destructor, or a destructor that is inaccessible from this constructor.
T is a non-union class with a variant member M with a non-trivial default constructor, and no variant member of the anonymous union containing M has a default member initializer.
and some additional rules for union types.
tl;dr: it's complicated.
Implicit default constructors are not created for all objects.
The main rule is that when an object has no constructors of any kind, it gets assign an implicit default constructor.
I won't go over all the specific rules dictating when they get created, you're better off reading them from here.
As for your question 1 on the error message:
I tried to declare the object author inside the constructor instead of initializer list. It gave me error.
You don't show the code that produced the error, so I will assume it is like below - correct me if I'm wrong.
// sample A - Bad code, wont compile
class Author { };
class Book
{
public:
Book(int x, Author y): n(1) {
a(y); //-this line does NOT compile.
// initialization of a must be in the initializer list,
// between : and {
}
private:
Author a;
int n;
};
The reason the above does not compile is because it is a language rule that nested objects declared by value must be initialized in one of these 2 ways:
- within the initializer list
- implicitly, by letting the compiler call the default constructor - which will work if the object has one.
Finally, on your question 2, yes, that sample declaration of Point does invoke the default constructor, if the class has one. Again, refer to language reference to clarify on when the default constructor exists or not.
This is really question on C++ language, what does SNeuron(int NumInputs); mean inside the structure? I'm not c++ programer and this construction inside structure looks strange to me. Can anybody explain it what it could be for? I already tried google.
struct SNeuron
{
//the number of inputs into the neuron
int m_NumInputs;
//the weights for each input
vector<double> m_vecWeight;
//ctor
SNeuron(int NumInputs);
};
A struct in C++ is exactly the same as a class, except that all members of a struct are public by default.
So what you are seeing here is simply a constructor declaration for the struct.
The reason, I believe, is to make interoperability with C easier.
It's simply declaring a constructor for the struct SNeuron. This is called a prototype method, and won't wok unless it's implemented later on. It could be implemented inside the class by saying
SNeuron(int NumInputs) {
// Constructor code
}
or outside like this:
SNeuron::SNeuron(int NumInputs) {
// Constructor code
}
The main use of this would be to initialize the fields m_NumInputs and m_vecWeight.
When an instance of the structure is created, it need to be "constructed" (i.e. initialized), that is done by having constructor functions, which are automatically called by the compiler when an instance is created.
For example, in the following declaration and definition of a variable using the structure, the constructor will be called:
SNeuron myNeuron(5); // Creates the instance and calls the constructor function
That is simply a constructor. A constructor is basically a mechanism by which you initialize all the data members of a class when an object of that class type is created.
You can write constructors for both struct and class.
But that constructor which you declared in your code is not the default constructor because a default constructor is that constructor which takes no arguments.
I've started trying out the C++11 standard and i found this question which describes how to call your ctor from another ctor in the same class to avoid having a init method or the like. Now i'm trying the same thing with code that looks like this:
hpp:
class Tokenizer
{
public:
Tokenizer();
Tokenizer(std::stringstream *lines);
virtual ~Tokenizer() {};
private:
std::stringstream *lines;
};
cpp:
Tokenizer::Tokenizer()
: expected('=')
{
}
Tokenizer::Tokenizer(std::stringstream *lines)
: Tokenizer(),
lines(lines)
{
}
But this is giving me the error:
In constructor ‘config::Tokenizer::Tokenizer(std::stringstream*)’:
/path/Tokenizer.cpp:14:20: error: mem-initializer for ‘config::Tokenizer::lines’ follows constructor delegation I've tried moving the Tokenizer() part first and last in the list but that didn't help.
What's the reason behind this and how should i fix it? I've tried moving the lines(lines) to the body with this->lines = lines; instead and it works fine. But i would really like to be able to use the initializer list.
When you delegate the member initialization to another constructor, there is an assumption that the other constructor initializes the object completely, including all members (i.e. including the lines member in your example). You can't therefore initialize any of the members again.
The relevant quote from the Standard is (emphasis mine):
(§12.6.2/6) A mem-initializer-list can delegate to another constructor of the constructor’s class using any class-or-decltype that denotes the constructor’s class itself. If a mem-initializer-id designates the constructor’s class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the is the target constructor. [...]
You can work-around this by defining the version of the constructor that takes arguments first:
Tokenizer::Tokenizer(std::stringstream *lines)
: lines(lines)
{
}
and then define the default constructor using delegation:
Tokenizer::Tokenizer()
: Tokenizer(nullptr)
{
}
As a general rule, you should fully specify that version of the constructor that takes the largest number of arguments, and then delegate from the other versions (using the desired default values as arguments in the delegation).
I have a singleton class for which I need a private member. I want that member to be empty until I use my setter method to set the right data.
class PlaybackHelper{
private:
PlaybackHelper();
PlaybackHelper(PlaybackHelper const&);
void operator=(PlaybackHelper const&);
playback_type type;
Note note;
public:
void setPlaybackType(playback_type aType);
static PlaybackHelper &getInstance();
};
Xcode is giving me an error in my implementation file (where I'm implementing my private constructor) saying that I should initialize my member:
PlaybackHelper::PlaybackHelper(){
}
error: Semantic Issue: Constructor for 'PlaybackHelper' must explicitly initialize the member 'note' which does not have a default constructor
I don't understand why I'm not able to do this (especially since it's not giving me any errors for the playback_type type; (enum) member which works the same way) Any ideas what I could do to leave my Note member empty until I'm ready to assign a value to it?
playback_type is a plain old data, thus lacking of initializing type simply leaves it as uninitialized; However, class Note's non-default constructor is defined, and thus its default constructor would not be generated automatically if you did not define it.
To solve it, you could either
initialize it with the parameters of (one of the) non-default constructors defined by you.
PlaybackHelper::PlaybackHelper() : note(/*...*/)
{
}
Define a default constructor for class Note
The error message is clear - there's no default constructor for Note. Either create one, or initialize Note in the initializer list with an existing constructor.
I want that member to be empty until I use my setter method to set the right data.
You can't. Both note and playback_type exist when you create your object.
Since Note doesn't have default constructor (i.e parameterless constructor), you have to initialize it in the member initialization list as:
PlaybackHelper::PlaybackHelper() : note(/*..args...*/)
{ //^^^^^^^^^^^^^^^^^^^^member initialization
}
Pass the appropriate argument(s) to note as required by Note constructor. You've to do the same, for other constructor of PlaybackHelper a well.