I'm still new to C++ and I'm trying to know if it is possible to access a function from another class knowing that no one is the father class here . This is a piece of my program to show you what I want to do exactly .
class CSubject
{
public:
CSubject() = default;
CSubject(std::string m_Name){this->Name = m_Name;}
void print(){ std::cout << Name;}
~CSubject(){}
private:
std::string Name;
};
class CStudent
{
public:
CStudent() = default;
void Method2()
{
//Call the print method and print the name "test"
}
~CStudent(){}
private:
};
int main()
{
CSubject AE("test");
CStudent ST;
ST.Method2(); //Print test;
return 0;
}
Forget about classes for a second. You want to call Method2(), and from there, print information that was put into the AE. Suppose you didn't have two classes of your own, but rather, say:
void Method2();
int main() {
const char* AE = "Test";
// ...
Method2();
}
That wouldn't work, right? And it shouldn't work, because local variables in a function (like main()) are usable only within that function's body; that's their local scope. For Method2() to use AE in any way, you have to let Method2() "know" about it. It's the same with classes.
You could use static method and attributes, which can be altered by creating an instance and overwriting it and also getting them from unrelated processes.
I would edit your CSubject class like this:
class CSubject {
public:
CSubject() = default;
CSubject(std::string m_Name) {
CSubject::Name = m_Name;
}
static void print() {
if (CSubject::Name.empty()) //checking is a good practice
std::cout << "The name is empty...\n";
else
std::cout << Name;
}
~CSubject() {}
private:
static std::string Name;
};
And you could access the print method from your Method2 like this:
void Method2() {
CSubject::print();
}
But beware! The static attribute is the only one for the class. If you plan on creating multiple CSubject instances and their new names, then you could store the m_Name attribute as non-static private, print() as non-static public, and Method2 should have a parameter where you pass the CSubject (the whole object or just the data that you need) that is in your interest.
Related
I'm new to OOP and I'm working on a C++ project. I isolated my problem to make answering easy but here's the real scenario:
I have a superclass member function, that modifies values inside the object that called it. The modification is based on a value coming from another object of the same class. This object is given to the function as the only parameter. Such as:
void BaseClass::function(BaseClass x) {}
However, I created a subclass. And if the parameter is a subclass type, I want to modify its unique attribute, too.
void BaseClass::function(DerivedClass x) {}
The problem is that the subclass is obviously defined later in the code.
I don't want it as two separate methods, because the calculation algorithm is already written inside, and also the solution I search for doesn't require to change the code at the places where the function is already in use. Besides, every other possibility that comes to mind (e.g. using typeid()) looks silly.
#include <iostream>
#include <string>
class Base
{
protected:
//common attribute
const std::string name;
public:
//constructor for common attribute
Base(const std::string nameString) : name(nameString) {}
//getter
std::string getName() { return name; }
//superclass as parameter
void test1(Base &example) { std::cout << example.getName(); }
//subclass as parameter (I'd want the line below to work)
//void test2(Derived &example) { std::cout << example.getNumber(); }
};
class Derived : private Base
{
protected:
//unique attribute
const std::string number;
public:
//constructor
Derived(const std::string nameString, const std::string numberString) : Base(nameString),
number(numberString) {}
//getter for unique attribute
std::string getNumber() { return number; }
};
int main ()
{
Base object = Base("whatever");
Base baseParameter = Base("base");
Derived derivedParameter = Derived("derived", "12");
object.test1(baseParameter);
//object.test2(derivedParameter);
return 0;
}
What is the standard way of doing it?
You could make test2 a template, and ensure that it's only used with types derived from Base:
template<typename Derived>
void test2(Derived &example)
{
static_assert(std::is_base_of_v<Base, Derived>);
std::cout << example.getNumber();
}
Here's a demo.
I have a large class with many methods. This class has a subclass that manages a different situation.
Just to clear it up with an example the actual situation is the following:
class Logic {
public:
virtual void method()
{
Something::getInstance()->doSomething();
}
};
class ArrayLogic : public Logic {
private:
Something** array;
public:
void method() override
{
for (int i = 0; i < AMOUNT; ++i)
array[i]->doSomething();
}
};
Now this pattern repeats itself in multiple methods and I'd like to have just one implementation without trading for performance (since some of this methods are actually already proven to require efficiency).
I was thinking if it's possible with C++11 to have a template solution approach which is able to manage this situation at compile time without the necessity to duplicate the code.
Mind that the array doesn't make sense to exist for Logic so having a Something*[1] is not a viable option.
An additional problem is that at the moment Something** array is not directly contained in ArrayLogic but resides in another class, so it's more like
class ArrayLogic : public Logic {
private:
Container* container;
public:
void method() override {
for (int i = 0; i < AMOUNT; ++i)
if (container->array[i])
container->array[i]->doSomething();
}
}
While having to check for container->array[i] != nullptr may seems strange the fact is that the position is relevant, so an element removed from the array doesn't cause a shift of the successive element but leaves a hole.
I'd try and create separate classes for single and multiplayer games. Base both of these on a base class LogicBase that has a method(Something*) function that calls doSomething() on its parameter. This is what #Pradhan was referring to.
In your main game, you can use a LogicBase* to refer to either a SinglePlayerLogic or a MultiPlayerLogic object and call the relevant method() using a virtual function call.
I'm passing what is stored in Container to the constructor of MultiPlayerLogic. But it could be in a separate class and accessed that way. Similarly, it may be cleaner to pass a Something to the constructor of SinglePlayerLogic, but I wanted to keep the code structure close to your original, so didn't do this.
It initially looks funny for LogicBase to call to a subclass, then have those subclasses call the protected method(Something*) back in the super class. I've seen it elsewhere as a design pattern, but can't recall it's name.
#include <iostream>
#include <vector>
const int AMOUNT = 5;
struct Something {
void doSomething() { std::cout << "Something::doSomething\n"; }
static Something* getInstance() { static Something s; return &s; }
};
class LogicBase {
public:
virtual void method() = 0;
protected:
void method(Something* s) { s->doSomething(); }
};
class SinglePlayerLogic : public LogicBase {
public:
void method() override
{
std::cout << "SinglePlayer::method\n";
LogicBase::method(Something::getInstance());
}
};
class MultiPlayerLogic : public LogicBase {
public:
MultiPlayerLogic(Something **s) : players(s) {}
void method() override
{
std::cout << "MultiPlayer::method\n";
for (int i = 0; i < AMOUNT; ++i) {
if (players[i] == nullptr) {
continue;
}
std::cout << i << " ";
LogicBase::method(players[i]);
}
}
private:
Something** players;
};
int main() {
LogicBase* lb;
SinglePlayerLogic spl;
lb = &spl;
lb->method();
std::vector<Something*> players{AMOUNT};
MultiPlayerLogic mpl(players.data());
lb = &mpl;
lb->method();
}
I'm trying to access members of a classC from classB, both classC and classB are inside classA. Here is what I'm trying to do;
//hello.h
class hello{
public:
hello();
class letters{
public:
letters();
void setName(char n);
char getName();
private:
char name;
}
class sayHi{
public:
sayHi();
void onJoin();
}
}
//hello.cpp
hello::hello(){}
hello::letters(){}
hello::sayHi(){}
void hello::letters::setName(char n){
hello::letters::name = n; //trying to access the private variable 'name' inside class letters
}
char hello::letters::getName(){
return hello::letters::name = n;
}
void hello::sayHi::onJoin(){
cout<< hello::letters::getName() <<endl;
}
I know i'm doing it wrong, am I supposed to create instances of each class and call the members?
Yes, you're supposed to create instances of the classes.
These are frequently called "objects", which is why they call it "object-oriented programming".
First, your getName and setName should look like this:
void hello::letters::setName(char n) {
name = n;
}
char hello::letters::getName() const { // Declaration should also say "const".
return name;
}
With that out of the way, any sayHi instance needs to know which letters to say "Hi" to, which means that you need to tell it.
This is usually done by passing a parameter to the method that needs to know:
class sayHi{
public:
sayHi();
void onJoin(const letters& who)
{
cout << who.getName() << endl;
}
};
which you would use somewhat like this:
int main()
{
hello::letters letter;
letter.setName('p');
hello::sayHi greeter;
greeter.onJoin(letter);
}
What is the error you are getting ? where have you created objects for accessing these methods ? Also
return hello::letters::name = n;
this line is wrong, it should be
return hello::letters::name;
I am making a simple console game in C++
I would like to know if I can access members from the 'entPlayer' class while using a pointer that is pointing to the base class ( 'Entity' ):
class Entity {
public:
void setId(int id) { Id = id; }
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
void setName(string name) { Name = name; }
string getName() { return Name; }
};
Entity *createEntity(string Type) {
Entity *Ent = NULL;
if (Type == "player") {
Ent = new entPlayer;
}
return Ent;
}
void main() {
Entity *ply = createEntity("player");
ply->setName("Test");
ply->setId(1);
cout << ply->getName() << endl;
cout << ply->getId() << endl;
delete ply;
}
How would I be able to call ply->setName etc?
OR
If it's not possible that way, what would be a better way?
It is possible by using a cast. If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast:
Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");
If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. Note that you can only use dynamic_cast if the base class has at least one virtual function. An example:
Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
p->setName("Test");
}
That said, it would be far better to encapsulate your class's functionality using polymorphism (i.e. virtual functions).
Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. So, you need to add a virtual destructor to the base class.
I would consider doing something like this:
public:
void setId(int id)
{
Id = id;
}
void virtual setName( string name ) = 0; // Virtual Function
string virtual getName() = 0; // Virtual Function
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
entPlayer() {
Name = "";
Id = 0;
}
void entPlayer::setName(string name) { // Must define function
Name = name;
}
string entPlayer::getName() { return Name; } // again must define function here
};
You can do a dynamic cast:
entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base);
This will (if successful) result in a derived pointer.
Otherwise NULL is returned.
C++ makes what you are trying to do really awkward, because this is probably not what you should be doing, and it is trying to lead you to good object-oriented design. In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work.
Without knowing your broader context, it's hard to say what you should do instead. What I can say is that if you wanted a more specific pointer, you should have put a ring on it you almost certainly shouldn't use a function that returns an Entity*, and there is probably a better approach.
I have two classes in C++, where one inherits from the other:
class A {
public:
virtual void Initialize(){
m_MyString = "Default value";
}
protected:
string m_MyString;
}
class B : public A {
public:
void Initialize(){
A::Initialize();
m_MyString = "New Value";
}
}
Is there a difference between the above class B and this one?
class B : public A {
public:
void Initialize(){
A::Initialize();
A::m_MyString = "New Value";
}
}
It seem using the scoping operator will result in a the string having garbage, correct? I'm thinking when it overrides, the A::m_MyString is different than B::m_MyString. Does this even make sense?
I'm seeing the variable get set in A, then when we return to B, have garbage. This has to do with "hidden" vs. overridden?
Your code is not valid in many ways. It should look like:
class A { // << errors were here
public:
virtual void Initialize(){
m_MyString = "Default value";
}
protected:
string m_MyString;
}; // << lost ;
class B : public A // << errors were here
{
public:
virtual void Initialize(){ // << virtual
A::Initialize(); // has no effect in the end
A::m_MyString = "New Value"; // same as `m_MyString = "New Value";`
}
}; // << lost ;
In the code above there is no difference with m_MyString. Post your actual code with error.
If your code looks like:
class B : public A
{
public:
virtual void Initialize(){
// here is a difference
A::m_MyString = "New Value";
m_MyString = "New Value";
}
protected:
string m_MyString; // !!! overridden
};
Then there is a difference because B has two instances of m_MyString: A::m_MyString and B::m_MyString.
Are you calling Initialize() from the constructor of A?
Calling virtual methods in constructors is not recommended. For example, if A's constructor looked like
A::A() {
Initialize();
}
B's Initialize method would never get called.
Seeing your actual code would help a lot.
There is no difference between those two versions of class B. Is that the real code that you see garbage in?
The compiler should tell you if you're calling a virtual function from a constructor. But if not, that's definitely a problem.
I think you can make a virtual function final in the derived class, but maybe not. The variable should be the same, regardless of whether or not you explicitly define scope, unless you have a variable of the same name in the derived class.
If this is how your code looks:
using namespace std;
class A
{
public:
virtual void Initialize()
{
m_MyString = "Default value";
}
protected:
string m_MyString;
};
class B : public A
{
public:
void Initialize()
{
A::Initialize();
m_MyString = "New Value";
}
void display()
{
cout<<m_MyString<<endl;
}
};
int main()
{
B b;
A a;
b.Initialize();
b.display();
return 0;
}
Then there is no difference between the two versions of the class B that you described in your question. I added the display function just to make the values clear. By the definitions of the class that you have given, the m_MyString is not being overridden. So the m_MyString variable will have "New Value" assigned to it, i.e. both the classes A and B will share the variable m_MyString.
If you override the m_MyString in class B like
class B : public A
{
public:
void Initialize()
{
A::Initialize();
m_MyString = "New Value";
}
void display()
{
cout<<m_MyString<<endl;
}
protected:
string m_MyString;
};
Then the value of B::m_MyString will contain "New Value" and the Value of A::m_MyString will contain "Default value".
It seem using the scoping operator will result in a the string having garbage, correct?
No, this should work and m_MyString will have "New Value" after b.Initialize() is called.
I'm thinking when it overrides, the A::m_MyString is different than B::m_MyString. Does
this even make sense?
No, when a class B inherits another class A, the object of class B will have a union of the data members of the two. In this case, there is only one m_MyString that is A::m_MyString.
I'm seeing the variable get set in A, then when we return to B, have garbage.
This has to do with "hidden" vs. overridden?
No, there is only one instance of m_MyString.
You definitely need to read this - http://www.openrce.org/articles/files/jangrayhood.pdf.