Can a struct be inherited in C++?
Yes, struct is exactly like class except the default accessibility is public for struct (while it's private for class).
Yes. The inheritance is public by default.
Syntax (example):
struct A { };
struct B : A { };
struct C : B { };
Other than what Alex and Evan have already stated, I would like to add that a C++ struct is not like a C struct.
In C++, a struct can have methods, inheritance, etc. just like a C++ class.
In C++, a structure's inheritance is the same as a class except the following differences:
When deriving a struct from a class/struct, the default access-specifier for a base class/struct is public. And when deriving a class, the default access specifier is private.
For example, program 1 fails with a compilation error and program 2 works fine.
// Program 1
#include <stdio.h>
class Base {
public:
int x;
};
class Derived : Base { }; // Is equivalent to class Derived : private Base {}
int main()
{
Derived d;
d.x = 20; // Compiler error because inheritance is private
getchar();
return 0;
}
// Program 2
#include <stdio.h>
struct Base {
public:
int x;
};
struct Derived : Base { }; // Is equivalent to struct Derived : public Base {}
int main()
{
Derived d;
d.x = 20; // Works fine because inheritance is public
getchar();
return 0;
}
Of course. In C++, structs and classes are nearly identical (things like defaulting to public instead of private are among the small differences).
Yes, c++ struct is very similar to c++ class, except the fact that everything is publicly inherited, ( single / multilevel / hierarchical inheritance, but not hybrid and multiple inheritance )
here is a code for demonstration
#include<bits/stdc++.h>
using namespace std;
struct parent
{
int data;
parent() : data(3){}; // default constructor
parent(int x) : data(x){}; // parameterized constructor
};
struct child : parent
{
int a , b;
child(): a(1) , b(2){}; // default constructor
child(int x, int y) : a(x) , b(y){};// parameterized constructor
child(int x, int y,int z) // parameterized constructor
{
a = x;
b = y;
data = z;
}
child(const child &C) // copy constructor
{
a = C.a;
b = C.b;
data = C.data;
}
};
int main()
{
child c1 ,
c2(10 , 20),
c3(10 , 20, 30),
c4(c3);
auto print = [](const child &c) { cout<<c.a<<"\t"<<c.b<<"\t"<<c.data<<endl; };
print(c1);
print(c2);
print(c3);
print(c4);
}
OUTPUT
1 2 3
10 20 3
10 20 30
10 20 30
Related
This question already has answers here:
Order of constructor call in virtual inheritance
(3 answers)
Closed 7 years ago.
I've heard that using the virtual keyword solves the diamond problem.
However, when I did this:
#include <iostream>
using namespace std;
class A {
public:
A(int x = 100) {
num = x;
}
protected:
int num;
};
class B1 : virtual public A{
public:
B1(int x = 50) : A(2*x) {
}
};
class B2 : virtual public A{
public:
B2(int x = 50) : A(2*x) {
}
};
class C : public B1, public B2 {
public:
C(int x = 75) : B1(2*x), B2(2*x) {};
int getData(){ return num; }
};
int main() {
C c(10);
cout << c.getData();
cin.get();
return 0;
}
It displays the output as 100 instead of what I expected, i.e. 40. Why?
When you use virtual inheritance, you are guaranteed to have one single instance of the common base class (cite); therefore, B1 and B2 cannot have their own instance of A, but they will share a single instance with C. For instance, if you define C's constructor as follows:
C(int x = 75) : B1(2*x), B2(2*x), A(x) {};
you'll see your code outputs 10. The key is in what #dyp has commented:
the common base class is initialized in the most derived class
(Of course in the example above it doesn't make any sense to have all B1, B2 and A in the initializer list, as having Awill suffice).
This is a code fro diamond tree problem of multiple inheritance
and according to me this code is cool but it is showing some error on compilation
..help me to figure the error
#include<iostream>
using namespace std;
class A //A Diamond tree problem
{
int x;
public:
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(20) { }
};
class D: public B, public C{
};
int main()
{
D d;
d.print();
return 0;
}
It would be useful to see the error:
In constructor ‘D::D()’:
error: no matching function for call to ‘A::A()’
When using virtual inheritance, the virtual base class must be initialised by the most derived class. In this case, that is D; so in order to be able to instantiate D, it must initialise A:
class D: public B, public C
{
public:
D():A(42) {}
};
Alternatively, you could provide A with a default constructor. Declaring any constructor will prevent the compiler from implicitly generating one for you.
You need to provide default construct for D and call A in member initialize list:
class D: public B, public C{
public:
D():A(30){}
};
Or you could provide a default A constructor
A():x(0) {}
I've been away from C++ for a while, and I'm having a little trouble with this one. I'll spare you my bad code - can someone please post a 'model answer' for how to write a simple header file and source file for a small class with a constructor that accepts a few values, and passes a few on to it's base classes constructor? I'm worried that I'm making something inline by mistake. Thank you.
Sometimes the simplest answers are the hardest to find clear examples of on the internet.
// ExampleClass.h
#ifndef ExampleClass_H_
#define ExampleClass_H_
#include "ExampleBase.h"
class ExampleClass : public ExampleBase {
public:
ExampleClass(int a);
};
#endif
// ExampleClass.cpp
#include "ExampleClass.h"
ExampleClass::ExampleClass(int a) : ExampleBase(a)
{
// other constructor stuff here
}
The initializer list is used to initialize the base classes. Initialize base classes before instance members. Non-virtual base classes are initialized from left to right, so if you have multiple bases, initialize them in the order they are declared.
Here's an example of passing arguments to the base class constructor:
#include <iostream>
struct Base {
Base(int i) {
std::cout << i << std::endl;
}
};
struct Derived : public Base {
Derived(int i) : Base(i) {}
};
Seeing as the OP requested non-inline versions, I'll repost with modifications.
struct Base {
Base (int);
};
struct Derived : public Base {
Derived (int);
};
Derived :: Derived (int i)
: Base (i)
{
}
class Parent
{
// Parent Constructor
Parent(int x)
{
// Constructor Code
}
};
class Child : public Parent
{
// Child Constructor
Child(int x, int y, int z) : Parent(x)
{
// Constructor Code
}
};
#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
The code above compiles fine in clang 3.0 and g++ 4.5. However the output is junk (--i.e., not three). Since the compiler doesn't seem to mind, how do I get the code to behave ?
Secondly, If there is some way to make the above slice / conversion to work correctly, how bad would it be if I then did the following, provided a good reason to do it exists :
class c : public a { public: uint64_t x; };
Why I am interested in these semantics.
The reason I want to do this is this. I have a two class heirachies, where one heirarchy (the parent) aggregages objects, on the same heirarchy level, from the other(the child). I use a custom container for the aggregation. I want to typedef the container in the parent class (the typedefs have the same name), and declare the container with the same name at each level of the parent.
The class heirarchies are designed to contain less information at lower levels ( the base classes hold the least), therefore slicing makes perfect sense here.
Edit:
There you go, this should clear things up.
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
The child B has more members than the child class A. However, I wan't to present a uniform interface for code that is only interested in the members of class A.
There is no way to do that if you directly set b::x. a::x and b::x are two different members, and the latter hides the former.
You can still access a::x on an object of type b with static_cast<a&>(bee).x = 3, but the fundamental problem is that the values of a::x and b::x on an object of type b are not synchronized.
If you abstract access to both x members with a "property getter/setter", then you can arrange for the setter on the derived class to also update the member of the base class. Or (maybe this is more appropriate?) you can make the member of the base class protected and use it from the derived class directly, slicing as you need just before returning from the getter.
huh ! its a bit complicated no ?
why don't you use :
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
or
virtual void setA( int value ) { b::x = value; }
or
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
There are two ways of constructing a software design; one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
C.A.R.Hoare
According to Jon's answer, Since a::x and b::x are separate variables, furthermore since b::x masks a::x, if you wanted to get the correct semantics you need to provide a copy conversion constructor. The following code does the trick.
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
Maybe try something like this:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};
Why I can't access base class A's a member in class B initialization list?
class A
{
public:
explicit A(int a1):a(a1)
{
}
explicit A()
{
}
public:
int a;
public:
virtual int GetA()
{
return a;
}
};
class B : public A
{
public:
explicit B(int a1):a(a1) // wrong!, I have to write a = a1 in {}. or use A(a1)
{
}
int GetA()
{
return a+1;
}
};
class C : public A
{
public:
explicit C(int a1):a(a1)
{
}
int GetA()
{
return a-1;
}
};
A's constructor runs before B's, and, implicitly or explicitly, the former construct all of A's instance, including the a member. Therefore B cannot use a constructor on a, because that field is already constructed. The notation you're trying to use indicates exactly to use a constructor on a, and at that point it's just impossible.
To build on Alex' answer, you can initialize the base class' "a" member by controlling its construction, like so:
class B : public A
{
public:
explicit B(int a1) : A(a1) { } // This initializes your inherited "a"
...
};
Note that I'm constructing the base class (capital "A") above, rather than attempting to directly initialize its inherited member (lowercase "a", drawing from your example).
To build even further on pilcrow's answer, you could easily initialize the A member like you want by overriding it in your B class:
class B : public A
{
public:
int a; // override a
explicit B(int a1) : a(a1) // works now
{
}
...
};
Though, I wouldn't necessarily recommend this ;)