How to initialise Constructor of a Nested Class in C++ - c++

I am getting problems in initializing the nested class constructor.
Here is my code:
#include <iostream>
using namespace std;
class a
{
public:
class b
{
public:
b(char str[45])
{
cout<<str;
}
}title;
}document;
int main()
{
document.title("Hello World"); //Error in this line
return 0;
}
The error I get is:
fun.cpp:21:30: error: no match for call to '(a::b)'

You probably want something like:
class a
{
public:
a():title(b("")) {}
//....
};
This is because title is already a member of a, however you don't have a default constructor for it. Either write a default constructor or initialize it in the initialization list.

You have to either make your data member a pointer, or you can only call the data member's constructor from the initialiser list of the construtor of the class it is a member of (in this case, a)

This:
document.title("Hello World");
is not "initializing the nested class"; it's attempting to call operator() on the object.
The nested object is already initialised when you create document. Except that it's not, because you've provided no default constructor.

So what do you have here:
class A {
B title;
}
Without defining constructor for class A (as Luchian Grigore shown) title will be initialized as: B title();
You can work that around by:
A::A():title(B("Hello world"))
// Or by adding non parametric constructor:
class B {
B(){
}
B( const char *str){
}
}
Object title (in document) is already initialized and you cannot call constructor anymore, but you still may use syntax: document.title(...) by declaring and defining operator() but it won't be constructor anymore:
class B {
const B& operator()(const char *str){
cout << str;
return *this;
}
}

Related

Is there a way to initialize a member object of a class within the constructors code instead of the initializer list?

Consider I want to wrap some library code inside an object. That library needs to be set up and initialized by calling some function inside the constructor of that wrapper class.
The librarie's "objects" then diverge into creating more, different "objects" that the wrapper class wraps in form of yet another wrapper object that should be a plain member of that class.
But as far as I see it, members of classes can only be initialized or created by calling their constructor in the initalizer list of the constructor. The execution of these bits of code preceed the constructor of the actual class that does the initialization of the library and its environment, making it impossible for me to actually initialize that member object as a member and instead force me to initialize it as a pointer to the 2nd wrapper, because its constructor must be called manually within the first constructor's code.
Example:
class A {
public:
A() {
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
//initialize b
}
private:
B b; //Wants to be a member but can not
};
class B {
B(ptr_to_some_library_metadata *a);
}
Member objects can only be constructed in the member initializer list. There are a few techniques which can be used to make it possible to initialize an object, though:
Use a helper [lambda] function doing the necessary extra work before return a suitable object. For example:
A()
: B([]{
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
return library_function();
}()) {
}
You can delay construction by using a union with just the appropriate member. When using this technique the member needs to be explicitly destructed, for example:
class A {
union Bu { B b };
Bu b;
public:
A() {
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
new(&b.b) B(library_function());
}
~A() {
b.b.~B();
}
// ...
};
I'd personally use the first approach. However, there are cases when using a union to delay construction is helpful.
Initializer lists are there to use another constructor than the default constructor.
But nothing impedes you for creating a custom function that will initialize b:
class A {
public:
A():b(init()) {
}
private:
B b; //Wants to be a member but can not
static B init()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
return B(a);
}
};
Wrap your library inside a class:
class LibraryWrapper
{
public:
LibraryWrapper()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
lib_data.reset(library_function()); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
}
//~LibraryWrapper() {/**/}
//LibraryWrapper(const LibraryWrapper&) {/**/} // =delete; ?
//LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?
//private: // and appropriate interface to hide internal
std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};
class B {
public:
explicit B(ptr_to_some_library_metadata *a);
// ...
};
And use extra member or inheritance:
class A
{
public:
A() : b(lib.lib_data.get()) {}
private:
LibraryWrapper lib; // placed before B
B b;
};

Why can't I use a class object as a parameter

I have this problem with getting class to pass as a parameter for another class constructor. Basically the code is like this:
class A
{
public:
int ID;
A(int getID)
{
ID = getID;
}
}
and I want to use that class A as a member of class B like this:
class B
{
public:
A someA;
A someB;
int number;
B(A ObjectA, A ObjectB, int getNumber)
{
someA = ObjectA;
someB = ObjectB;
number = getNumber;
}
};
The errors are basically saying that there is no matching function to call B::B(). I don't know whats wrong with it. I have done similar things with vectors of object, so I thought why cant this thing works. Any inputs/correction is appreciated, thank you!
Sidenotes: I have tried adding a default constructor for B as suggested in another thread, but it ended up saying invalid use of B::B.
Use the initialization list for your objects:
B(A ObjectA, A ObjectB, int getNumber)
:someA(std::move(ObjectA)), someB(std::move(ObjectB)), number(getNumber)
{
}
This will use the default move constructor from your class.
I used move here because you are passing your objects by value, so it makes sense to move them. If you passed them by const&, then don't move them and use the default copy constructor.
Still, this is about A default constructor, there is no problem with the B default constructor in the code you showed.
The error happens because you didn't tell B how to initialize its A attributes, so it's looking for the default A constructor.
In C++ the attribute initialization is made as show by Matthieu, and not in the constructor's body. You can add a default A constructor, but you have to think if it's the behavior you want for your code.
Compiling the code below doesn't show any error.
class A {
public:
int ID;
A() {}
A(int getID) {
ID = getID;
}
};
class B {
public:
A someA;
A someB;
int number;
B() {}
B(A ObjectA, A ObjectB, int getNumber) {
someA = ObjectA;
someB = ObjectB;
number = getNumber;
}
};

Difference between passing arguments to the base class constructor in C++

What is the difference in passing arguments to the base class constructor?
Dog::Dog(string input_name, int input_age) : Pet(input_name, input_age) { }
Dog::Dog(string input_name, int input_age) { Pet(input_name, input_age); }
Look the following snippet:
class Cat {
private:
const int m_legs;
public:
Cat() : m_legs{4}
{
}
};
In the snippet above this is the only way you have to initialize a constant because m_legs is initialized before the body of constructor.
Another case is exeptions managment:
class Test {
private:
ICanThrow m_throw;
public:
Cat() try : m_throw{}
{
}
catch(...)
{
// mangage exception
}
};
I usually prefer initialize member before ctor body or when I can initialize members directly in the class declaration:
class Cat {
public:
void meow()
{
}
private:
const int m_legs = 4;
string m_meow{"meow"};
};
If Pet has no default constructor, only 1) will work.
By the time you get into the actual body of the constructor all members and bases have already been constructed. So if a base class has no default constructor you need to tell the compiler which constructor you want it initialised with, and do it before the body of the constructor - this is what the initialiser list is for.
Another reason is if a base or member is const - you can't modify it in the body of the constructor.

How to call a parameter constructor of a class that contains a copy constructor as private,in c++?

I have a class that consists of a parameterized constructor which I need to call while creating an object. The class also contains a private copy constructor restricting to create an object to it. Now how to call the paramter constructor of this class. I think we can create a pointer reference to the class. But how to call the parameter constructor using the reference?
My Program:
#include<iostream>
#include<string>
using namespace std;
class ABase
{
protected:
ABase(string str) {
cout<<str<<endl;
cout<<"ABase Constructor"<<endl;
}
~ABase() {
cout<<"ABASE Destructor"<<endl;
}
private:
ABase( const ABase& );
const ABase& operator=( const ABase& );
};
int main( void )
{
ABase *ab;//---------How to call the parameter constructor using this??
return 0;
}
The syntax you need is ABase *ab = new ABase(foo); where foo is either a std::string instance or something that std::string can take on construction, such as a const char[] literal, e.g. "Hello".
Don't forget to call delete to release the memory.
(Alternatively you could write ABase ab(foo) if you don't need a pointer type.)
You can't do this. Because your ctor is protected. Please see (not related with your state, but only to learn more): Why is protected constructor raising an error this this code?

Class with no name, constructor, destructor

I've read about class with no name...
Got that
class
{
int i;
};
is not valied while
class
{
int i;
}A;
is valid.
But how to have a: 1) constructor and :2) destructor and: 3) how to pass as an argument???
If the class is unnamed then it can't have a custom constructor/destructor (although the compiler will generate the usual default ones for you). That means you can't pass an argument to it at construction. However, there's probably nothing stopping you from either (1) adding one or methods to the class to pass data to it after construction, or (2) giving the class a name in the first place.
The second thing is valid, but you cannot access the member i since it will be private. It is valid only because You have created an object A of that class type.
To have a constructor, I think you have to give the class a name. Use this:
class myclass
{
int i;
public:
myclass(int a) //This is the constructor
{
i = a;
}
~myclass() //This is the destructor
{
//Whatever you want to do on destroying the object
}
};
and instantiate that class as follows:
myclass A(10);
or similarly.
Note: This is just my interpretation, it can be done in many other ways.
You are doomed using the class locally and accessing it through the local object A, only.
You can use it in a template, though:
template <typename T>
inline void print(const T& a) {
std::cout << a.x << std::endl;
}
int main()
{
class {
public: int x;
} a;
a.x = 1;
print(a);
}