For C++ learning purposes, I have the files class1.h, class1.cpp, class2.h and class2.cpp. I would like to instantiate an object named class1Obj inside class2. Where and how do I instantiate this object? Do I instantiate classObj inside the class2 constructor?
In the past I have created a pointer to a class, which worked well for that time, but I think a pointer is not the route I should take this time because the classObj will only be used inside class2.
class class1
{
//...
};
class class2
{
class1 member;
//...
};
In class2 ctor, you can initialize member in the constructor initialization list.
class2::class2(...)
: member(...)
{
//...
}
Well how did you create a pointer in the past? Presumably, you did something like this:
class class2
{
public:
class2()
{
class1Pointer = new class1();
}
// Destructor, copy constructor/assignment, etc...
private:
class1* class1Pointer;
};
Now you want to do exactly the same but this time you don't want a pointer to class1, you want a class1 itself:
class class2
{
public:
class2() {}
// Destructor, copy constructor/assignment, etc...
private:
class1 class1Obj;
};
The object will be default initialized when your class2 object is created. If your class1 constructor should take some arguments, use an initialization list:
class class2
{
public:
class2() : class1Obj(1, 2, 3) {}
// Destructor, copy constructor/assignment, etc...
private:
class1 class1Obj;
};
Instantiate a class inside a class :
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(int i)
{
}
};
class Bar
{
Foo i; //<--- instantiate a class inside a class ----
public:
Bar() : i(1) //<--- instantiate a class inside a class ----
{
}
};
int main(void)
{
Bar b;
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
It depends on your Class1. If its constructor accepts some parameters, then you must initialize it explicitly in Class2 constructor or in initialization list.
Class2 {
public:
class2() {
//Here m_class1Obj will be instantiated
m_class1Obj = Class1(/*some params*/);
}
private:
Class1 m_class1Obj;
};
Or
Class2 {
public:
class2() : m_class1Obj() {}
private:
Class1 m_class1Obj;
};
Related
class class1 {
public:
class1(int x);
};
class class2 : public class1 {
};
Can I do:
class2 my_class2(10);
Or do I have to define the constructor again for class2 (even though it does exactly the same thing)?
Since C++11 constructors can be inherited:
class class2 : public class1 {
public:
using class1::class1;
};
Otherwise you have to do the following:
class class2 : public class1 {
public:
class2(int x): class1(x) {}
};
A constructor of the base class has to be called anyway when constructing an object of the derived class.
Since C++17, you can directly call public base-class constructors via aggregate initialization - without adding any code to the classes:
class2 my_class2{2}; // Note the curly braces!
I have the following situation:
Factory class implementation:
class FactoryClassA {
public:
FactoryClassA(){};
~FactoryClassA(){};
ClassA create(double a, double b) {
return ClassA;
};
};
ClassA implementation:
class ClassA {
friend class FactoryClassA
~FactoryClassA() {}
private:
ClassA(double a = 0, double b = 0)
{
a(a),
b(b)
};
double a;
double b;
};
OtherClass implementation:
class OtherClass {
public:
OtherClass() {
ClassFactory myClassAFactory;
aClassA = myClassAFactory.create();
}
~OtherClass() {};
private:
aClassA;
};
Unfortunately, this does not work. Because in the (empty) member initializer list of OtherClass, the empty constructor of ClassA is called, which does not exist.
The reason why I made the constructor of ClassA private, is that I want the user to only create objects of ClassA through the FactoryClassA.
First of all, create() should have a return type:
ClassA create(double a, double b) {
return {a, b};
}
I am not going through all the other syntactic bugs. Please fix them, because others might find your question when they search for answers. Please make it easy for them to understand your question.
This has to be in your code after ClassA has been defined, because the compiler has to know the size of a ClassA object as well as the constructor to use.
Second, just initialize your members before the constructor body:
OtherClass() :
aClassA{ClassFactory{}.create(0.0, 0.0)}
{}
You might prefer to have create() as a static member function of ClassFactory. Then the OtherClass constructor looks like this:
OtherClass() :
aClassA{ClassFactory::create(0.0, 0.0)}
{}
That is more intuitive.
This code is full of small errors, that make it unuseable. First syntax for member initialization for a class is :
class A {
A(x, y): m_a(x) { ... }
...
}
and class declaration are statements so they need the final ;
Next, the dtor for a class must be public if you want to be able to use temporary objects.
The default values should not be in ClassA ctor but on create factory method.
Finally, you should use a static factory in OtherClass, no need to create a new factory for each object.
Code becomes:
class FactoryClassA;
class ClassA {
public:
friend class FactoryClassA;
~ClassA(){}
private:
ClassA(double a, double b):a(a),b(b){}
double a;
double b;
};
class FactoryClassA {
public:
FactoryClassA(){}
~FactoryClassA(){}
ClassA create(double a = 0, double b = 0) {
return ClassA(a, b);
}
};
class OtherClass {
public:
OtherClass(): aClassA(myClassAFactory.create()){}
~OtherClass(){}
private:
static FactoryClassA myClassAFactory;
ClassA aClassA;
};
FactoryClassA OtherClass::myClassAFactory;
Not far from original one, but this ones compiles...
I have some code like that:
class Class1 {
// some code here
Class2 inverse() {
// some code here
}
};
class Class2 : public Class1 {
// some code here
};
And I got an error that Class2 is unknown in function inverse. Can I declare that class and how?
You can forward declare Class2 before Class1. And then you'll have to separate your inverse function declaration from definition. So you should define its after Class2 is defined:
class Class2;
class Class1 {
// some code here
Class2 inverse();
};
class Class2: public Class1 {
// some code here
};
Class2 Class1::inverse()
{
return Class2();
}
But, honestly, it is bad design.
Class2 is not defined when you reach Class2 inverse() so even forward declaring would not completely solve that issue. However you can do two things. Either return a pointer or a reference to Class2
class Class2;
^^^^^^^^^^^^
class Class1 {
Class2& inverse() {
// ^^^ or possibly Class2*
//
}
};
class Class2: public Class1 {
}
Or defined inverse after Class2 have been completely defined
class Class2;
class Class1 {
Class2 inverse();
};
class Class2: public Class1 {
//
}
Class2 Class1::inverse() {
//
}
I would go with the second option if possible.
Ok, I have a class:
class class1
{
public:
class2 object2;
int a;
};
where:
class class2
{
public:
void function2();
};
Basically, I need function2 in object2 to be able to access "a." How would I go about doing this? Thanks.
class class2
{
public:
void Function2(class1& c1)
{
c1.a;
}
}
simple.
I'm trying to set up a copy constructor and i'm getting this error
class Class1{
public:
int get_data();
void set_data(int);
private:
int d;
};
int Class1::get_data(){
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
Class2(const Class2&);
};
Class2::Class2(const Class2 &c2) : Class1(){
set_data(c2.set_data());
}
whats a solution to this problem. i read some of the previous questions and i understand why this is happening. but making set_data() const is not an option.
whats the accepted approach for copy constructors?
thanks,
You could just write a constructor for Class1 taking an int parameter:
class Class1 {
explicit Class1 (int i) : d (i) {}
// as before
};
class Class2 : public Class1 {
Class2 (Class2 const & c2) : Class1 (c2.get_data ()) {}
};
However, the default copy constructor should be enought here (i.e. you don't need to write your own, the compiler will do it for you).
Generally speaking, you should use initialisation lists:
http://www.parashift.com/c++-faq-lite/ctors.html
in the constructors (read the whole entry in the faq)
Edit: You forgot the 'const' qualifier for your get_data function.
Don't you want:
set_data(c2.get_data());
(and make the Class1::get_data() member function const)?
But you really should be using constructor initialization lists:
Class2::Class2(const Class2 &c2)
: Class1(c2)
{
}
This code uses the compiler-generated default copy constructor for Class1. In many cases you shouldn't use the default copy constructor or copy-assign operator overload, but here it's fine because the sole data member of Class1 is an int object.
In fact, you could even rely on the compiler-generated default copy constructor for Class2.
EDIT: Here is some example code:
#include <iostream>
class Class1{
public:
Class1() : d(0) { } // Provide a no-arg constructor to initialize `d`
int get_data() const; // Class1::get_data() is `const` because it does not change the `Class1` object.
void set_data(int);
private:
int d;
};
int Class1::get_data() const{
return d;
}
void Class1::set_data(int data){
d = data;
}
class Class2 : public Class1{
public:
Class2();
};
Class2::Class2()
: Class1()
{
}
int main() {
Class2 other_c2;
other_c2.set_data(14);
Class2 c2(other_c2);
std::cout << c2.get_data() << '\n';
}
http://codepad.org/jlplTYrH