I'm new to c++. I created following classes Into, MyWstring as follows: I tried to create setter for an object variable as setInto method. It complains no such constructor Into(). What should I do? How to create setter for this? (Basically what is my expectation is how to achieve Java like setters in C++)
Into.h
#ifndef INTO_H_
#define INTO_H_
class Into {
public:
Into(int id1);
virtual ~Into();
int id;
};
#endif /* INTO_H_ */
Into.cpp
#include "Into.h"
Into::Into(int id1) {
// TODO Auto-generated constructor stub
id = id1;
}
Into::~Into() {
// TODO Auto-generated destructor stub
}
MyWstring.h
#ifndef MYWSTRING_H_
#define MYWSTRING_H_
#include<iostream>
#include"Into.h"
using namespace std;
class MyWstring {
public:
MyWstring(wstring test1);
virtual ~MyWstring();
void assign(MyWstring m);
void setInto(Into into1);
wstring test;
Into into;
};
#endif /* MYWSTRING_H_ */
MyWstring.cpp
#include "MyWstring.h"
MyWstring::MyWstring(wstring test1) {
test = test1;
}
MyWstring::~MyWstring() {
// TODO Auto-generated destructor stub
}
void MyWstring::assign(MyWstring m)
{
m.test = L"M";
}
void MyWstring::setInto(Into into1)
{
into = into1;
}
When you construct a MyWString, the compiler will call the constructors of all base classes (you don't have any), and sub-objects. If you don't provide an argument, it will call the constructor without arguments - and you don't have one. Your choices are:
Provide a default constructor:
....
Into(int id1);
Into();
...
Into::Into() : id(0) {} // Always prefer to initialize rather than assign later
Initialize MyWString::into:
MyWstring::MyWstring(wstring test1)
: test(test1)
, into(0)
{}
Your class has an instance variable into that has no default constructor (one without arguments).
When MyWstring is created, it needs to create an instance of Into, but cannot do so because it does not know how to.
Solution 1: Give Into a default constructor
class Into {
[...]
Into() : id(0) { }
};
Solution 2: Mention into in the initializer list for MyWstring:
MyWstring::MyWstring(wstring test1)
: test(test1), into(0)
{
}
Note the additional change of assigning test in the initializer list. Otherwise it gets default-constructed and then copy-assigned, which is probably not what you want.
If into does not have a sensible default value, you might need to re-think your logic and use a pointer to an Into object instead (but make sure to use std::unique_ptr<> or similar).
Try changing your MyWstring c'tor definition to this:
MyWstring::MyWstring(wstring test1)
:
into( 0 ),
test( test1 )
{
}
You have a variable of type Into in class MyWstring, which does not have a default c'tor and hence compiler can not instantiate it by itself.
Also it is better if your MyWString class accepts the value for the variable "into" in c'tor so that you have an actual value to set, instead of setting some default value.
The compiler is complaining that you don't have a default constructor.
The default constructor is called, When you construct an object without passing any arguments, e.g.
Into into;
The default constructor is also automatically called if your class is member of another class.
The default constructor is auto-generated if there is no user-declared constructor. In your case you have the constructor Into(int id1) which prevents the compiler from auto-generating a default constructor.
So what you need is one of the three lines below
Into():id(0){};
Into() = default; // C++11 syntax
Into():Into(0){}; // call another constructor from your constructor.
Alternatively, if you have a constructor where all its arguments have default values, the compiler will use that as the default constructor. So you can also do like this
Into(int _id = 0) : id(_id){};
If you don't want a default constructor for your class then you need to call the non-default one on the constructor of your other class.
MyWstring::MyWstring(wstring test1): test(test1), into(0)
{}
Now to the next part, you are assigning an object of type Into to another object of the same type which means that the copy assignment operator is being used here. You are in luck because in your case the compiler auto-generates the copy assignment operator.
Related
I wrote a class that holds an array of objects, which each expect a pointer to a c-struct in their constructor:
Here's some code:
class TheOtherClass
{
private:
SomeCStruct* m_pCStruct;
int m_ObjIdx;
public:
TheOtherClass::TheOtherClass(SomeCStruct* pCStruct, int ClassIdx)
: m_pCStruct(pCStruct),
m_ObjIdx(ClassIdx)
{}
}
class MyClass
{
private:
TheOtherClass m_objects[4];
SomeCStruct* m_pMyCStruct;
public:
MyClass::MyClass(SomeCStruct* pCStruct)
: m_pMyCStruct(pCStruct)
{
m_objects[4] = {TheOtherClass(&pCStruct, 1), TheOtherClass(&pCStruct, 2),
TheOtherClass(&pCStruct,3), TheOtherClass(&pCStruct, 4)};
}
I'd actually like to initialize the member objects of MyClass in the init list of the constructor but I was reading this isn't possible?
Hence I tried the above approach but I'm always getting the error: "TheOtherClass": no appropriate default constructor available.
Another thing to mention is that the compiler I'm running is a state of the art C++03 compiler ;-) (it's code for a DSP and TI sort of doesn't wants to update the compiler)
Any help would be highly appreciated!
Since MyClass(SomeCStruct* pCStruct) constructor doesn't (can't) initialize the TheOtherClass m_objects in the member initializer list, the m_objects will need to be default constructed at first, and then this member will be reassigned with new value in the body of the MyClass constructor.
The TheOtherClass won't have a synthesized constructor since you have defined (other, non-default) ctor that takes SomeCStruct* and int. Thus, no default constructor for it in your code.
Here, we define a default constructor:
class TheOtherClass {
SomeCStruct* m_pCStruct;
int m_ObjIdx;
public:
TheOtherClass() : m_pCStruct(nullptr), m_ObjIdx(0) {} // Default ctor
TheOtherClass(SomeCStruct* pCStruct, int ClassIdx)
: m_pCStruct(pCStruct),
m_ObjIdx(ClassIdx) {}
};
As to the MyClass. Since you've already pass the argument as a pointer MyClass(SomeCStruct* pCStruct), you don't need to take the address of it (as in &pCStruct).
And the main issue in the MyClass is that the m_objects is of class type TheOtherClass which does not define any operator=, including the one that takes brace-enclosed initializer list. So, you won't be able to do like so:
m_objects[4] = { // The operator '=' has not been defined for the TheOtherClass, also note the subscript
TheOtherClass(pCStruct, 1),
TheOtherClass(pCStruct, 2),
TheOtherClass(pCStruct,3),
TheOtherClass(pCStruct, 4)
};
Again, when you try to list initialize it, it has already been default constructed. Thus, for this approach to work you will need to define such copy-assignment operator to do this kind of assignment to an already default constructed instance of the TheOtherClass. As to how to implement this operator, it will mostly depend on the overall design and other factors which were not mentioned in this thread.
Update
If you will have the following body of the MyClass constructor, it will work:
MyClass(SomeCStruct* pCStruct) : m_pMyCStruct(pCStruct) {
// Assign to default initialized TheOtherClass object
m_objects[0] = TheOtherClass(pCStruct, 1);
}
I would advise you to check these:
Operator overloading
Constructors and member initializer lists
I have a class which looks something like this:
class X
{
std::variant<CComPtr<ID2D1HwndRenderTarget>, CComPtr<ID2D1DCRenderTarget>> mpRenderTarget;
void init();
}
// To early to know which member we need, it's no value until derived class calls init() method.
X::X() : mpRenderTarget(nullptr)
void X::init()
{
// Only here it is known what exactly to initialize!
// and this is going to be in derived class, this one pure virtual.
}
Problem is that this constructor doesn't compile, because variant initialization is not valid,
however if I omit initialization of mpRenderTarget in constructor then another problem is that
the variant is "ilformed" according to standard.
I just want to initalize it to some default in constructor, but how?
Simply assign it a default value of one of the types:
X::X() : mpRenderTarget(CComPtr<ID2D1HwndRenderTarget>{}) {}
You can be explicit about the default pointer value being nullptr as well:
X::X() : mpRenderTarget(CComPtr<ID2D1HwndRenderTarget>{nullptr}) {}
The important part is that you must specify which of the variant types you want to initialize the object with.
Sometimes I don't want to provide a default constructor, nor do I want the compiler to provide a system default constructor for my class. In C++ 11 I can do thing like:
class MyClass
{
public:
MyClass() = delete;
};
But currently my lecturer doesn't allow me to do that in my assignment. The question is: prior to C++ 11, is there any way to tell the compiler to stop implicitly provide a default constructor?
I would say make it private.. something like
class MyClass
{
private:
MyClass();
}
and no one(from outside the class itself or friend classes) will be able to call the default constructor. Also, then you'll have three options for using the class: either to provide a parameterized constructor or use it as a utility class (one with static functions only) or to create a factory for this type in a friend class.
Sure. Define your own constructor, default or otherwise.
You can also declare it as private so that it's impossible to call. This would, unfortunately, render your class completely unusable unless you provide a static function to call it.
Since c++11, you can set constructor = delete. This is useful in conjunction with c++11's brace initialization syntax {}.
For example:
struct foo {
int a;
foo() = delete;
foo(int _a) {
// working constructor w/ argument
}
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
see https://en.cppreference.com/w/cpp/language/default_constructor#Deleted_implicitly-declared_default_constructor
Additionally to declaring the default constructor private, you could also throw an exception when somebody tries to call it.
class MyClass
{
private:
MyClass()
{
throw [some exception];
};
}
help me in getting the concept of default constructor with example.
i don't know when to use default constructor in the program and when not to.
help me coming over this problem.explain it with an example for me.
when it is necessary to use it?
#include<iostream>
using namespace std;
class abc
{
public:
abc()
{
cout<<"hello";
}
};
int main()
{
abc a;
system("pause");
return 0;
}
so actually what is the use of default constructor and when it is necessary to use it?
A class that conforms to the concept DefaultConstrutible allows the following expressions (paragraph 17.6.3.1 of N3242):
T u; // object is default initialized
T u{}: // object is value intialized
T(); T{}; // value initialized temporary
So much for the concept. Paragraph 12.1/5 actually tells us what a default constructor is
A default constructor for a class X is a constructor of class X that
can be called without an argument. If there is no user-declared
constructor for class X, a constructor having no parameters is
implicitly declared as defaulted (8.4). An implicitly-declared default
constructor is an inline public member of its class. ...
With the introduction of deleted special member functions, the standard also defines a list of cases where no implicit default constructor is available and the distinction of trivial and non-trivial default constructors.
If you don't need to do anything as your class is instantiated. Use the default constructor, any situation else you will have to use your own constructor as the default constructor basically does nothing.
You also don't need to write any "default" constructor.
class abc {
};
int main() {
abc a; //don't want to do anything on instatiation
system("pause");
return 0;
}
class abc {
private:
int a;
public:
abc(int x) { a = x };
}
int main() {
abc a(1); //setting x to 1 on instantiation
system("pause");
return 0;
}
Constructor is a special function, without return type. Its name must be as the class\struct name. It doesn't have an actual name as a function, as Kerrek-SB pointed out.
Default constructor is the one that has no parameters, or has parameters all with a default value.
Constructor function is being called only once - when an object is instantiated
Constructor is called through a new expression or an initialization expression. It cannot be called "manually".
Useful for initializing object's fields, usually with a member initializer list.
Check this.
Default constructor is constructor with no argument and will be called on these situations:
Instancing or newing an object of a class without any constructor, like:
abc a;
abc* aptr=new abc;
Declaring an array of a class, like:
abc a_array[10];
When you have a inherited class which does not call one of base class constructors
When you have a feature in your class from another class and you don't call a definite constructor of that feature's class.
When you use some containers of standard library such as vector, for example:
vector <abc> abc_list;
In these situations you have to have a default constructor, otherwise if you do not have any constructor, the compiler will make an implicit default constructor with no operation, and if you have some constructors the compiler will show you a compile error.
If you want to do one of the above things, use a default constructor to make sure every object is being instantiated correctly.
I'm not an C++ expert and still do not have a great intuitive grasp of how things works. I think this is a simple question. I am having trouble passing objects with state to other objects. I'd prefer to avoid passing pointers or references, since once the initialized objects are setup, I call them millions of times in a tight loop. I think I'm dong something like a Command pattern. Here's the core of the problem. My header code is something like:
class ObjectWithState {
public:
ObjectWithState(int state) { // This constructor creates the problem!
state_ = state; // everyting works with no constructor.
}
private:
int state_;
};
class TakesObject {
public:
TakesObject(ObjectWithState obj) {
obj_ = obj;
}
private:
ObjectWithState obj_;
};
My main() functions looks like:
int main () {
ObjectWithState some_object(1);
TakesObject takes_object(some_object);
return 0
}
I get the following error (g++):
test.h: In constructor 'TakesObject::TakesObject(ObjectWithState)':
test.h:14: error: no matching function for call to 'ObjectWithState::ObjectWithState()'
test.h:5: note: candidates are: ObjectWithState::ObjectWithState(int)
test.h:3: note: ObjectWithState::ObjectWithState(const ObjectWithState&)
Simple answer?
I not sure if this has to do with copy constructors. If so, I'm trying to find a solution that keeps the class definition of ObjectWithState very clean and short. Users of this library will be defining lots of small functions like that which will be used by TakesObject function. Ideally programmers of the ObjectsWithState just need to focus on implementing a simple object. Perhaps I'm going astray...
What you may want to do is use the member initialisation syntax:
class TakesObject {
public:
TakesObject(ObjectWithState obj): obj_(obj) {
}
private:
ObjectWithState obj_;
};
In your posted code, the TakesObject constructor will first try to construct a new ObjectWithState with its default constructor, then call the assignment operator to copy the passed-in obj to obj_. The above example constructs the obj_ directly using its copy constructor.
You will also need to define a copy constructor for your ObjectWithState class, too:
class ObjectWithState {
public:
ObjectWithState(int state) {
state_ = state;
}
ObjectWithState(const ObjectWithState &rhs) {
state_ = rhs.state_;
}
private:
int state_;
};
If you omit all constructors from your class declaration, then the compiler supplies a default and a copy constructor for you. If you declare any constructors, then the compiler supplies no default or copy constructor, so you must implement your own.
You're getting this error because you're declaring a constructor. The compiler will provide the default constructor only if you don't declare a constructor in your class. Because you have declared a constructor, you don't get the default one. You have to explicitly declare a constructor with no parameters.