I have class A with basic members and functions:
class A{
public:
typedef struct{
int aa;
int bb;
} stEntry;
stEntry entry;
void function1();
void function2();
};
Than class B that should extend class A including structure stEntry...
class B : public A{
public:
typedef struct :stEntry
{
int cc;
} stEntry;
stEntry entry;
void function3();
};
and then:
int main() {
A a;
B b;
a.entry.aa = 1;
b.entry.aa = 2;
b.entry.cc = 3;
cout << "class A:"<<sizeof(a)<< endl;
cout << "class B:"<<sizeof(b)<< endl;
return 0;
}
I get
class A:8
class B:20
So class B contains 2 instances - 8 bytes(A class member) + 12 bytes(B class member).
Is there a way how to extend structure stEntry for class B? (without have 2 instances)
No, because you're creating two instances yourself. The base class has an instance, and the derived class has an instance (of a class extending the base class' inner class).
You can't modify the structure of the base class outside of it - once you defined it, it stays like that.
Sort of, with virtual inheritance:
struct stEntryBase {
int aa;
int bb;
};
struct A : virtual stEntryBase {
typedef stEntryBase stEntry;
void function1();
void function2();
};
struct stEntryDerived : virtual stEntryBase {
int cc;
};
struct B : A, stEntryDerived {
typedef stEntryDerived stEntry;
void function3();
};
If you want to go another level of inheritance then B would derived virtually from stEntryDerived.
Now you have to refer to the fields as a.aa, b.cc, there is no member entry. Also, the stEntry types are no longer POD (so bb and cc may no longer be adjacent in memory). Finally, the size increase due to the virtual inheritance might actually be bigger than two ints.
What you can do, is get an stEntryDerived* or stEntryDerived& from an instance of B. Then that pointer/reference can be used to access aa, bb, and cc as the members of stEntryDerived, without the user needing to know about B. So you've achieved separation of interface, at some cost.
Related
Here is what UML looks like CLASS UML
ClassA has an pointer to ClassB, and ClassB has a pointer to ClassC. I was wondering if I can access functions of ClassA in ClassC without inheriting ClassA.
Q: I was wondering if I can access functions of ClassA in ClassC without inheriting ClassA.
A: Yes, it is possible to access functions of ClassA in ClassC. Either by calling static member functions of classA or by providing specific instance of classA to ClassC. It may look like that classA can be accesed by following the pointers in reverse direction (ClassC to ClassB to ClassA) but that is not possible. Pointers point to values only in one direction.
This is interesting question about differences between a class and instances of class (objects). The following example shows why there is no classA::callAnyMethod():
#include <iostream>
class B;
class C;
class A
{
public:
A(B *next, int value) : next_(next), value_(value) { }
void af1() const { std::cout << value_ << "\n"; }
static void af2() { std::cout << staticValue << "\n"; }
protected:
B *next_;
int value_;
static int staticValue;
};
int A::staticValue = 3;
class B
{
public:
B(C *next) : next_(next) { }
protected:
C *next_;
};
class C
{
public:
void cf1(const A &a) { a.af1(); }
void cf2() { A::af2(); }
};
int main()
{
C c;
B b(&c);
A a1(&b, 1);
A a2(&b, 2);
// a1 is first instance of class A.
// One 'A::value_' is defined in a1 and is equal to 1.
c.cf1(a1);
// a2 is second instance of class A.
// Second 'A::value_' is defined in a2 and is equal to 2.
c.cf1(a2);
// Without specific instance of class A, we can use only static member
// 'A::staticValue' which is defined at file scope and is equal to 3.
// 'A::staticValue' is not part of objects (instances) of class A.
c.cf2();
return 0;
}
So, I'm in this situation right now. I have two classes A and B. The B is subclass of A and there's also a global object of the B class which is initialized in the main. A function of the A class uses that global object and calls its functions. In what order do I have to write the declarations in order for the compiler to read everything?
I keep getting the same errors whatever I try. Namely:
- (x) does not name a type
- invalid use of incomplete type (x)
- forward declaration of (x)
Code example:
class B;
B* B_GLOBAL;
class A{
public:
void A_function(){
B_GLOBAL->B_function();
}
private:
};
class B : public A{
public:
void B_function();
private:
};
int main(void){
B_GLOBAL = new B;
return 0;
}
Move the definition of A_function below the declaration of B:
class B;
B* B_GLOBAL;
class A{
public:
void A_function();
private:
};
class B : public A{
public:
void B_function();
private:
};
void A::A_function(){
B_GLOBAL->B_function();
}
int main(void){
B_GLOBAL = new B;
return 0;
}
I try to do something like this:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
B *myAttribute;
};
int main()
{
Inherited *i = new Inherited();
std::cout << i->returnAttrNumber(); // outputs 1, because it gets the A not the B. I want it to output 2, to get the B object in returnAttrNumber()
}
So, class Base holds an object A. Inherited holds an A-derived object B. And I try to call a method on the base class, but I want it to cast down in the hirarchy of the corresponding Object as far as possible (without static_cast or dynamic_cast) and then take the B object, not A and do stuff (returning it's number in in this case)
Is there a way to do that downcasting from a base class in C++ without big difficulties?
Thanks for answers!
This is very bad design. The quick answer is you can access variable from the base class via the fully qualified identifier. Take the following example:
#include <iostream>
class A
{
public:
A()
: var(1) {}
protected:
int var;
};
class B : public A
{
public:
B()
: var(2) {}
int getBVar() const
{
return var;
}
int getAVar() const
{
return A::var;
}
private:
int var;
};
int main()
{
B b;
std::cout << "A: " << b.getAVar() << std::endl;
std::cout << "B: " << b.getBVar() << std::endl;
}
Which outputs the following:
A: 1
B: 2
About the down casting bit... Base and Inherited have different variables. You can not safely case one to the other.
Well as rioki said,
Base and Inherited have different variables
This is because I redeclared MyAttribute as a B in Inherited. This was the mistake. I thought, when I declare it with the same name, it will be the same variable, that's wrong.
So the whole solution for this is to uncomment this one line in Inherited. Working code:
class A{
public:
A(){number = 1;}
int number;
};
class B : public A{
public:
B(){number = 2;}
};
class Base {
public:
Base() {myAttribute = new A();}
int returnAttrNumber(){return myAttribute->number;}
A *myAttribute;
};
class Inherited : public Base{
public:
Inherited(){myAttribute = new B();}
//B *myAttribute;
};
int main()
{
Base *i = new Inherited(); // this works, what is necessary in my case
std::cout << i->returnAttrNumber(); // outputs 2 now
}
I have a base class instance, there is a derived class that inherits from the base class, I want to transform the base instance into derived instance, (if possible without copying anything (maybe sending to the derived class a reference of the base class)) how can I achieve that?
Note: I need this because I'm using factory design pattern which identify the derived class needed to be created using a parameter located in the base instance.
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Thanks.
Consider the case of the car.
You can treat a Lamborghini as a car.
You can treat a Yugo as a car.
You can treat a car as a Lamborghini if it is a Lamborghini. In C++ this means a pointer to car that really points to a Lamborghini. In order to get a Lamborghini pointer back out of the car pointer you should use dynamic_cast. If the car does not point to a Lamborghini, dynamic_cast will return NULL. This keeps you from trying to pass off a Yugo as a Lamborghini and blowing the Yugo's engine.
But when the Lamborghini is being treated as a car, it can only do car things. If you copy a Lamborghini into a car, you strip out all Lamborghini-ness forever. It's gone.
Code time!
This, I'm afraid cannot be done:
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
C is being copied into a B and the B is being returned. B would need a constructor that took a C, but the point is moot. B cannot be instantiated if it's pure virtual. For now we'll ignore the leak that would be new C()
Also can't use a reference for this job, pretty much the same problem, so you're trapped into returning a pointer
B * BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Now I'm going to make a suggestion: Build the make function into B and handle the case where A doesn't map to anything recognized by B.
class B: public A
{
public:
virtual ~B(){}
static B * makeB(A & a)
{
switch(a.getN())
{
case 1:
return new C();
}
return NULL;
}
};
But this leads to another recommendation: Why should B know anything? And What is the point of A at this level? Why is A storing build codes for classes two or more steps down the hierarchy? Bad from a maintenance point of view. The point of objects is they know who they are and how to manipulate themselves. Short-circuiting this leads to pain.
class B: public A
{
public:
virtual ~B(){}
virtual B* makeB() = 0;
};
Now B only makes Bs, needs no help from A, and those who extend B are stuck with figuring out how to make themselves--a task they should know better than anyone else. Much safer because there is never any possibility of a code unrecognised by B for a new class.
class C: public B
{
public:
B* makeB()
{
return new C();
}
};
class D: public B
{
public:
B* makeB()
{
return new D();
}
};
Edit: Traditional factory
You're asking for an abstract factory. For that you need nothing. You don't even need a class. You certainly don't need a class A. The goal of this sort of factory is the caller knows nothing about the class. By providing an A, the caller needs to know how to make an A or have another factory that makes an A.
First a bit of set-up in a header file BFactory.h:
#ifndef BFACTORY_H_
#define BFACTORY_H_
#include <exception>
class B
{
public:
virtual ~B(){}
virtual std::string whatAmI() = 0;
protected:
// data members common to all B subclasses
};
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
B* BFactory(enum bType type);
#endif /* BFACTORY_H_ */
Here I'm going to deviate from the book way a little. Rather than using an integer to identify the type to be built, I'm going to use an enum. Two reasons: Easier to read and understand gimme_a_C than 1 and generates a compiler error if you try to provide a value that is not enumerated.
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
And an exception to flag stupidity if the enum is updated with new types (gimmie_an_E) but the factory is not.
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
This is all the Factory client needs to see. They don't see C. They don't see D. They have no clue that C and D exist in any way other than the names listed in enum bType. All they ever see is pointers to B.
Now for the implementation BFactory.cpp:
#include "BFactory.h"
class C:public B
{
std::string whatAmI()
{
return "C";
}
};
class D:public B
{
std::string whatAmI()
{
return "D";
}
};
B* BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return new C();
case gimmie_a_D:
return new C();
default:
throw BadTypeException();
}
}
I'll leave it up to the reader to spot the stupid bug in the above code that makes these error prone and why I don't like them.
And usage, main.cpp:
#include "BFactory.h"
int main()
{
B * temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
delete temp;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
delete temp;
//temp = BFactory(1001); // won't compile
try
{
temp = BFactory(gimmie_an_E); // will compile, throws exception
std::cout << temp->whatAmI() << std::endl;
}
catch(BadTypeException& wtf)
{
std::cerr << wtf.what() << std::endl;
}
}
There is still absolutely no use for or involvement of A. A if it exists, should no nothing about B or the children of B.
These days there is a little improvement we can make so that the pointers are a little safer. unique_ptr allows us to maintain the polymporphic advantages of a pointer to B without the memory management woes.
std::unique_ptr<B> BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return std::unique_ptr<B>(new C());
case gimmie_a_D:
return std::unique_ptr<B>(new D());
default:
throw BadTypeException();
}
}
and the new main:
int main()
{
std::unique_ptr<B> temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
}
You might want to define a constructor that takes the base class instance as the argument so you can later use static_cast to convert from the base class to the derived class.
class Derived : public Base
{
public:
Derived(const Base& base) : Base{base} {}
};
int main()
{
Base a;
Derived b = static_cast<Derived>(a);
}
If you want to create a derived class instance using the base class instance then there is some conversion rule between the two, which you can specify explicitly using a derived class constructor.
Although it is impossible to alter the type of an object you still can make instances of base and derived classes share the same data:
#include <memory>
#include <iostream>
class Base
{
protected:
struct CommonData
{
int A;
int B;
};
std::shared_ptr<CommonData> m_data;
public:
Base() : m_data(std::make_shared<CommonData>())
{
m_data->A = 0;
m_data->B = 0;
}
void SetData(Base * source)
{
m_data = source->m_data;
}
int A() const { return m_data->A; }
int B() const { return m_data->B; }
void SetA(int value) { m_data->A = value; }
void SetB(int value) { m_data->B = value; }
};
class Derived : public Base
{
public:
int C;
};
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Base base;
base.SetA(12);
base.SetB(46);
Derived derived;
derived.SetData(&base);
derived.C = 555;
cout << derived.A() << endl; // 12
cout << derived.C << endl; // 555;
cin.get();
}
A base class should not "know" about how to make its own derived class instances. That is the point of inheritance.
The "is a" relationship of derived classes means that any subclass instance will pass as a base class instance transparently, and you can treat it as one, and by default base class non-virtual methods are called on a base class reference, even if it a derived class instance. Only virtual methods use the derived class method.
In the case of creating a base class instance from a derived class you want to "slice" the instance data (normally a bad thing and normally a mistake).
class A{ // ... A stuff };
class B : A
{ // ... B stuff
A make_A() { return (A) B(*this); } // copy cast to A
};
Under no circumstances try to do this:
class B;
class A { // ...
B make_B() { return B(*this); }
};
That is inverted OO logic. It requires at least 2 scans of the source code, which C++ does not do. It fails.
class base
{
private:
int a;
};
class base2
{
private:
int b;
};
class derived:public base,public base2
{
private:
int c;
};
main()
{
base b;
derived d;
cout<<size of(base)<<size of(base2)<<size of(derived);
}
since int a and int b are private variables.so they are not getting inherited in derived class.so the output should be 4 4 4 but it is
output:4 4 12
why?
since int a and int b are private variables.so they are not getting inherited in derived class
That's wrong - of course they are getting inherited, the code in the base class wouldn't be able to work without them. It's just that derived cannot get to them, but it does not change the sizeof the derived class.
Consider this extension of your example:
class base {
private:
int a;
protected:
base() : a(123) {}
void showA() {cout << a << endl;}
};
class base2 {
private:
int b;
protected:
base2() : b(321) {}
void showB() {cout << b << endl;}
};
class derived:public base,public base2 {
private:
int c;
public:
derived() : c (987) {}
void show() {
showA();
showB();
cout << c << endl;
}
};
Even though your derived class cannot read or change a and b, it can show their values by calling the corresponding functions in its bases. Therefore, the variables must remain there, otherwise the showA and showB member functions wouldn't be able to do their work.
private: or protected: or public: annotations on member fields affect only visibility. But the fields are still in the classes.
Take several days to read a good C++ programming book.