(C++) Suppose I have two classes A and B. Class B has a pointer to class A along with a method. How exactly do I interpret what's going on in this case. When that method is called does it have access to the methods in Class A since it's pointing to a possible instance of A
Class A {
public:
void method1() const;
void method2() const;
}
Class B {
public:
A* method3(int);
void method4();
void method5();
}
Let me know if I'm being vague here or need to provide more info
Edit 1: So basically Class B creates objects that get stored in a map that is accessible by an integer key. Class A has methods that can manipulate any one of those individual objects. So I guess in this case method3() would take in the key of the map as input and then it fetches that object from the map and then the user can choose to do method1 or method2 from Class A to manipulate it.
i.e. The object being stored in the map could be like a game piece and the methods in Class A can like flip it or rotate it.
Why don't you just try it?
class A {
public:
void method1() const;
void method2() const;
}
class B {
public:
A *GetA(int i) { return &mapA[i];
void method3();
private:
std::map<int, A> mapA;
}
int main()
{
B b;
auto pA = b.Get(1);
pA->method1();
return 0;
}
As long as A has a default constructor, this should create new items in B's map if they don't exist.
Note that making class A method1 and method2 const means that they don't change anything in A, so they couldn't be functions which change any of A's state.
The member function A* method3(int) is going to return a pointer to an instance of the class A. Thus the compiler will reserve a proper amount of memory for it on the heap. Most probably you will need to create dynamically an instance of that class inside the function method3 and return the pointer pointing to it.
Related
In this code I am storing the address of object B in pointer type object of A.
If I call the function then the program must run the function of second class but it doesn't work and run function of 1st class.
If I put virtual before the parental class function then it moves towards other class function.
When I stored 2nd class address in pointer type object, program have to show 2nd class function. But it couldn't do this.
Why this is so?
#include<iostream>
using namespace std;
#include<conio.h>
class a
{
public:
void fun()
{
cout << "1st";
}
};
class b:public a
{
public:
void fun()
{
cout << "2nd";
}
};
class c :public a
{
public:
void fun()
{
cout << "3rd";
}
};
void main()
{
a *A;
b B;
c C;
A = &B;
A->fun();
_getch();
}
When i stored 2nd class address in pointer type object, program have to show 2nd class function...
Not, it does not. In C++ functions are associated with classes (types), not objects. So compiler looks at the type of the pointer your functions is called through. Then, it tries to find such function in the corresponding class definition.
In your case compiler sees "call to the function fun() through the pointer of type A" and it simply translates it to the address of fun() from class A.
*The callable function is stored elsewhere, but not inside the object.
Indeed, this is the point of "statically typed" languages: compiler looks at your object through the prism of the object`s type.
However, as was mentioned, if you want to make association of a function with particular object, you need to use the keyword virtual. This will create a virtual table for each object of class A (and all inherited from A). Then addresses of all functions marked is virtual will be stored inside this virtual table. Consequently, when inheriting class has its own implementation of a virtual function, the address of the new implementation will override the previous address inside the object`s virtual table.
Now, when you call fun() through the pointer of class A the control flow (now during the runtime) will make a lookup to the objects virtual table and will find an address to the function you expect.
class A
{
public:
virtual void fun()
{
cout << "1st";
}
};
class B
{
public:
void func() override
{
cout << "2nd";
}
}
void main()
{
a *A;
b B;
A = &B;
A->fun(); // -> "2nd"
// function address deduced at runtime
}
You need to use virtual keyword, otherwise inheritance might not work as you expected.
So change your class a as follows:
class a
{
public:
virtual void fun()
{
In c++, pointers are static. This means that they are always looking for the parent's functions, even if they are pointing to a child class. You can avoid this by declaring a:fun as virtual. Take a look at this:
http://www.cplusplus.com/doc/tutorial/polymorphism/
I have a class Object and some derived classes, eg class Bird : public Object. The functions Object::Render and Bird::Render are defined and implemented. (as a matter of fact, Bird::Render calls Object::Render)
I also have a vector<Object*> which is holding a bunch of Bird*s. Now, in the future, this vector will also hold other types of objects.
My question is: without knowing the type of an element of that vector, is it possible to execute its specific Render function, ie can
vector<Object*> objects;
object.push_back(new Bird());
// ...
objects[i]->Render(); // This should execute Bird::Render
As far as I can see, the last line only executes Object::Render (which makes sense, as to the calling function, this is a vanilla Object).
Is there any way to change that?
Object::Render should be virtual function and Bird should override Render function.
class Object
{
public:
virtual ~Object() {}
virtual void Render() = 0;
};
void Object::Render() {}
class Bird : public Object
{
public:
void Render() { Object::Render(); }
};
vector<Object*> objects;
objects.push_back(new Bird());
objects[0]->Render();
I have been using a dynamic array but I had to add and remove items. I've read it's not recommended to use realloc or to resize the arrays when one can simply use std::vector however I'm having problems in changing my array to a vector.
This is my current code:
int main(){
// This is what I'm doing now
State*arr[3];
int pos = 0;
arr[0] = new Menu();
// How do I change it to a vector? This is what I'm trying:
std::vector<State> vec;
vec.push_back(Menu());
...
}
However I keep getting error: "Cannot allocate an object of abstract type 'State'" What am I doing wrong?
These are class State and Menu:
class State
{
public:
virtual ~State() {};
virtual void capture_events() = 0;
virtual void logic() = 0;
virtual void render() = 0;
};
Menu : public State
{
public:
Menu();
~Menu();
void capture_events();
void logic();
void render();
};
You need extra indirection because State is a polymorphic base class. You can do this using std::unique_ptr from <memory>.
#include <memory>
std::vector<std::unique_ptr<State>> states;
states.emplace_back(new Menu());
It is very important to use std::unique_ptr<State> and not State*, because of exception safety. Consider the following:
std::vector<State*> states;
states.push_back(new Menu());
foo(); // what if foo throws an exception?
// the next line wouldn’t get executed!
for (auto ptr : states) delete ptr;
In contrast, std::unique_ptr uses RAII to make sure the objects are always deleted if the vector goes out of scope, even in the case of early returns or exceptions. For further reference, see The Definitive C++ Book Guide and List.
You cannot instantiate a class which has pure virtual methods, i.e. a method like
virtual void func() = 0;
The =0means that you must derive the class and implement this method there. This derived class can be instantiated.
As long as a class contains pure virtual methods you cannot instantiate it and you will get your error.
If you use a vector you objects must be default constructible. You can not construct a object of your class State if one of the virtual methods is marked with =0 to set the class abstract. The idea to have a abstract class is that you can't create objects of that class.
What you maybe want to do:
Create a class family with a abstract base like your State. Create a vector of pointers to instances( objects) of your class. Create the objects with new and push_back the pointer to your vector. If you erase some elements don't forget to delete the objects with delete.
Don't forget to make the destructor of your family also virtual!
Something like that:
class Base
{
virtual void Do() =0;
virtual ~Base();
};
class A: public Base
{
void Do() { ... }
}
class B ...
class C ...
// Create your vector somewhere...
vector<Base*> myVect;
void AddObject()
{
// It is not important which kind of object you create. Base* obj can "hold" every
// object which is build from a class which is derived from Base!
Base* obj=new A();
myVect.push_back(obj);
}
void DeleteObj( Base* obj )
{
myVect.erase( ...find the object...);
delete obj;
}
void PopBack()
{
Base* ptr = myVect.back(); // get last object pointer
delete ptr; // delete the object
myVect.pop_back(); // remove pointer to object from vector
}
I also have a similar design question now in my work assignment. I have a base class like
class base
{
protected:
update()
{
// do some stuff with a and b, call it as action A
}
int a, b;
};
class derived : public base
{
protected:
update()
{
// want to do the same action A , but with varaiables c and d
}
int c, d;
};
and the requirement is, derived class requires both the operations , such as action on "a and b" AND "c and d" aslo. Hence , is it okay to design a method like update(int, int) , so that I can pass parameters as and when required "a and b" AND "c and d" and perform action on them .And I know that I can write a helper method to perform that action, but this action is specific to this class I cant separate it from this. Can I have any other better alternative for this.
In realtime its a bigger class and the action also not on integers ,its on some objects in turn, and the varibales should be related to the class.
You can call the base class implementation from the derived class implementation. Just call base::update(). Look here for example.
Yes that is perfectly valid:
class base
{
protected:
void update()
//^^^^ You forgot the return type.
{
doUpdate(a, b);
}
void doUpdate(int& x, int& y)
{
// do some stuff with x and y
// Because x and y are passed by reference they affect the original values.
}
private: // Should probaly make the member vars private
int a, b;
};
class derived : public base
{
protected:
void update()
//^^^^ You forgot the return type.
{
doUpdate(c, d);
}
private: // Should probaly make the member vars private
int c, d;
};
I would revisit whether your class derived has an is-a relationship (as you show) or a has-a relationship, like this:
class contains
{
protected:
base x, y;
update() { x.update(); y.update(); }
};
What you're asking is technically feasible, just define
void update(int& a, int &b)
and inside the update body forgot about the class memebrs and always refer to the parameters and call it as
update(a,b) or update(c,d).
The point, here, is to understand if update is really a member function (that requires also to access other member variables) or just a static member (that leaves in the class space, but doesn't see class members itself) and if the relation between the classes is correct (that merely means embedding vs inheritance). But these aspects should be based on consideration other than just the ones related on a single call...
C++ : I have a basic object (object A) that contains a member object (object B). The member object interface (object B) needs to be fully exposed through the pointer to object A. What's the best way to do this? I could place the object as a public member but this feels like a hack. I could write wrappers for all B's interface in A but this feels ugly. I could merge the objects but I am doing class serialization to XML so having distinct classes is cleaner. I thought about friend classing but I don't think that applies to this situation.
What is the standard way to resolve this type of issue?
Let B implement an interface IB. A manages an instance of B internally and has a getter getB that returns the IB interface of the private B instance. If you want to protect the B instance, you can make the IB methods const and also hide the destructor (by making it private in IB).
class IB {
private:
~IB();
public:
virtual void method1() = 0;
virtual void method2() = 0;
};
class B : public IB {
public:
virtual void method1() {};
virtual void method2() {};
void destruct() { delete this; }
};
class A {
private:
B myB;
public:
IB *getB() { return &myB; }
};
(This is just to give an idea. It's been 3+ years since I last touched C++. I could have made some blatant errors.)
I reject the notion that doing this at all is a good idea, but I would make it a public member. If you don't like that you can have a getB() method. If possible, I would make it return a const reference instead of a normal reference.
Overload the -> operator in A and in the implementation return the pointer variable of type B.
But as you know you will not be able to access A's members through A's pointer and ->. Also it has the risk of causing confusion who ever read the code.
I meant something like this.
struct A
{
B *p;
B * operator -> ()
{
return p;
}
};