Struggling with pointers to functions and references - c++

I am working through this problem I found on Git to brush up on some skills. Using friend is prohibited. C++ styling should be used compared to C.
Essentially, I cannot call the identify() function that belongs to the Brain member variable in my Human class. It just will not let me access it. If you can code this up, and explain where I am going wrong, that would be great.
Create a Brain class, with whatever you think befits a brain. It will have an Identify() function that returns a string containing the brain's address in memory, in hex format, prefixed by 0x.
Then, make a Human class, that has a constant Brain attribute with the same lifetime. It has an identify() function, that just calls the identity() function of its Brain and returns its result.
Now, make it so this code compiles and displays two identical addresses:
int main(){
Human bob;
std::cout << bob.identify() << "\n";
std::cout << bob.getBrain().identify() << "\n";
}
Here is what I have so far:
#pragma once
#include "Brain.h"
class Human
{
const Brain humanBrain;
public:
Human();
std::string identify();
};
#include "Human.h"
#include <iostream>
#include <string>
#include <sstream>
Human::Human()
{
this->humanBrain = new Brain;
}
std::string Human::identify()
{
Brain b = this->humanBrain.identify(); // This is essentially what I am trying to call--and I can't access it.
const Brain * ptr = humanBrain;
std::ostringstream test;
test << ptr;
return test.str();
}
#pragma once
#include <string>
#include <iostream>
class Brain
{
int age;
std::string gender;
void* ptr;
public:
Brain();
//std::string getBrain();
const std::string identify();
void setPtr(void* p);
};
#include "Brain.h"
#include <iostream>
#include <sstream>
Brain::Brain()
{
age = 10;
gender = "male";
}
const std::string Brain::identify()
{
//const Brain* bPtr = &this;
const Brain* bPtr = this;
ptr = this;
std::ostringstream test;
test << &bPtr;
std::string output = "Brain Identify: 0x" + test.str();
return output;
}

Your Human::humanBrain member is declared as type const Brain, which is correct per the instructions, however your Brain::identify() method is not qualified as const, so you can't call it on any const Brain object. This is the root of the problem that you are having trouble with.
In addition, there are many other problems with your code, as well:
Human::humanBrain is not a pointer, so using new to construct it is wrong. And, you don't need a pointer to get the address of a variable anyway. Nor do you actually need a pointer to the member at all in this project.
Human lacks a getBrain() method, so bob.getBrain() in main() will not compile, per the instructions.
Human::identify() is calling humanBrain.identify(), which returns a std::string as it should, but is then assigning that string to a local Brain variable, which is wrong (not to mention, you are not even using that variable for anything afterwards). The instructions clearly state that Human::identity() should simply call Brain::identify() and return its result, but you are not doing that.
Brain::identify() is printing the address of its local variable bPtr rather than printing the address of the Brain object that identify() is begin called on, per the instructions.
With all of that said, try something more like this instead:
Human.h
#pragma once
#include "Brain.h"
#include <string>
class Human
{
const Brain humanBrain;
public:
Human() = default;
std::string identify() const;
const Brain& getBrain() const;
};
Human.cpp
#include "Human.h"
std::string Human::identify() const
{
return humanBrain.identity();
}
const Brain& Human::getBrain() const
{
return humanBrain;
}
Brain.h
#pragma once
#include <string>
class Brain
{
int age;
std::string gender;
public:
Brain();
std::string identify() const;
};
Brain.cpp
#include "Brain.h"
#include <sstream>
Brain::Brain()
{
age = 10;
gender = "male";
}
std::string Brain::identify() const
{
std::ostringstream test;
test << "Brain Identify: 0x" << this;
return test.str();
}

Related

C++ Pointer function to other class function

I need help with passing a function pointer on C++. I can't linkage one function for a class to other function. I will explain. Anyway I will put a code resume of my program, it is much larger than the code expose here but for more easier I put only the part I need to it works fine.
I have one class (MainSystem) and inside I have an object pointer to the other class (ComCamera). The last class is a SocketServer, and I want when the socket received any data, it sends to the linkage function to MainSystem.
ComCamera is a resource Shared with more class and I need to associate the functions ComCamera::vRecvData to a MainSystem::vRecvData or other function of other class for the call when receive data and send de data to the function class associate.
Can Anyone help to me?
EDDITED - SOLUTION BELOW
main.cpp
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include <exception>
#include <unistd.h>
using std::string;
class ComCamera {
public:
std::function<void(int, std::string)> vRecvData;
void vLinkRecvFunction(std::function<void(int, std::string)> vCallBack) {
this->vRecvData = vCallBack;
}
void vCallFromCamera() {
this->vRecvData(4, "Example");
};
};
class MainSystem {
private:
ComCamera *xComCamera;
public:
MainSystem(ComCamera *xComCamera) {
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iChannelNumber, std::string sData) {vRecvData(iChannelNumber, sData); });
}
void vRecvData(int iNumber, string sData) {
std::cout << "RECV Data From Camera(" + std::to_string(iNumber) + "): " << sData << std::endl;
};
};
int main(void) {
ComCamera xComCamera;
MainSystem xMainSystem(&xComCamera);
xComCamera.vCallFromCamera();
return 0;
}
Output will be:
MainSystem RECV Data From Camera(4): Example
You can have ComCamera::vRecvData be of type std::function<void(int, std::string)> and then have ComCamera::vLinkRecvFunction() be like this:
void ComCamera::vLinkRecvFunction(std::function<void(int, std::string)> callBack)
{
this->vRecvData = callBack;
}
and have MainSystem constructor be like this:
MainSystem::MainSystem(ComCamera *xComCamera)
{
using namespace std::placeholders;
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iNumber, std::string sData){vRecvData(number, sData);});
}
Still though the original question has way too much code to go through friend.
Here what you want :
#include<iostream>
using std::cout;
class A; //forward declare A
class B{
public:
void (A::*ptr)(int x); //Only declare the pointer because A is not yet defined.
};
class A{
public:
void increase_by(int x){
a+=x;
} // this function will be pointed by B's ptr
int a = 0; // assume some data in a;
B b; // creating B inside of A;
void analyze(int y){
(*this.*(b.ptr))(y);
} // Some function that analyzes the data of A or B; Here this just increments A::a through B's ptr
};
int main(){
A a; // creates A
cout<<a.a<<"\n"; // shows initial value of a
a.b.ptr = &A::increase_by; // defines the ptr that lies inside of b which inturns lies inside a
a.analyze(3); // calls the initialize method
(a.*(a.b.ptr))(3); // directly calls b.ptr to change a.a
cout<<a.a; // shows the value after analyzing
return 0;
}
Output will be :
0
6
I still don't get why would you do something like this. But maybe this is what you wanted as per your comments.
To know more read this wonderful PDF.

Weird behavior with OOP and string pointers

Here's my code:
#include <iostream>
#include <string>
class Human
{
public:
std::string * name = new std::string();
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << Human::name << std::endl;
}
int main()
{
Human * martha;
martha->name = new std::string("Martha");
martha->introduce();
return 0;
}
Well, it's supposed to print a message out like:
"Hello, my name is Martha" but it doesn't print neither the "Hello, my name is" string or the "Martha" name. Why does it occur?
The fix is simple and is to completely remove all pointers; see the code below. There are a number of issues with your code that I could address in detail, including memory leaks, uninitialized variables, and general misuse of pointers, but it seems that you're possibly coming from a different language background and should spend time learning good practice and the important semantics and idioms in modern C++ from a good C++ book.
#include <iostream>
#include <string>
class Human
{
public:
std::string name;
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human martha;
martha.name = "Martha";
martha.introduce();
return 0;
}
Few modifications are required to the code.
Updated code along with the comments to the change made are included below.
#include <iostream>
#include <string>
class Human
{
public:
//Removed pointer to a string
//Cannot have an instantiation inside class declaration
//std::string * name = new std::string();
//Instead have a string member variable
std::string name;
void introduce();
};
void Human::introduce()
{
//Human::name not required this is a member function
//of the same class
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human *martha = new Human();
//Assign a constant string to string member variable
martha->name = "Martha";
martha->introduce();
return 0;
}
As suggested by #alter igel - The Definitive C++ Book Guide and List would be a good place to start.
#include <iostream>
#include <string>
class Human {
public:
void Human(std::string* n) { name = n; }
void introduce();
private:
std::string* name;
};
void Human::introduce() {
std::cout << "Hello, my name is " << name << std::endl;
}
int main() {
Human* martha = new Human(new std:string("Martha"));
martha->introduce();
return 0;
}
Try that. The difference is that you don't initialise the variable in the class definition, and you initialise the name with the constructor. You can split the method definition out into it's own section, but it's only one line and is fine being inside the class definition.

std::sting ? string does not name a type error

I got these 2 files for now and anytime I want to compile I get the error
string does not name a type
in Bestellung.h on the line with std::string name;.
Why?
main.cpp
#include "Bestellung.h"
#include <iostream>
using namespace std;
int main()
{
Bestellung();
cout << Bestellung{"maki"} << endl;// [maki,10€]
}
Bestellung.cpp
#include "Bestellung.h"
Bestellung(string bestellV, double preisV = 10){
name = "bestell V";
preis = "preis V";
};
string get_name const(Bestellung v) {
return Bestellung.name;
};
double get_preis const(Bestellung v){
return Bestellung.preis;
};
ostream& print(ostream&) const {
};
Bestellung.h
#ifndef BESTELLUNG_H
#define BESTELLUNG_H
#include <string>
#include <iostream>
class Bestellung{
std::string name;
std::double preis;
public:
Bestellung(string, double = 10);
string get_name const {
};
double get_preis const {
};
ostream& print(ostream&) const {
};
};
#endif
You have to use a namespace qualifier. You have:
Bestellung(string,double=10);
You should have:
Bestellung(std::string,double=10);
You also have:
string get_name const {
You should have:
std::string get_name const {
If you don't want to specify the std namespace every time you use a string, you can do this near the beginning:
using std::string;
Doing that in header files is bad practice though, so I would just use the full qualifications like I said to first.
After correcting this error, you need to do the same thing to that ostream you have too.
Read more about namespaces here.

C++ Pass an object into another object?

I don't know if I've missed something, but I can't seem to figure out how to make this work, and couldn't find the answer online.
Lets say I have a two classes, Class A, and Class B. (stored in separate files)
Class A has a function setName() that sets a variable within a Class A object.
Class B has a function setOtherName() that sets the value of a Class A object's name.
So I set setOtherName() up like so:
void setOtherName(ClassA& cla)
{
*cla.setName("foobar");
}
then my main script looks like so:
Class A burger;
Class B fries;
fries.setOtherName(*burger);
this does not work in my orignal script, I get the following error:
error: no matching function for call to 'ClassB::setOtherName(ClassA*&)
Any help is aprreciated! ( sorry for any confusion )
Actual code:
main.cpp:
#include <iostream>
#include "quests.h"
#include "player.h"
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
quests GameQuests;
player Player;
GameQuests.quest1(Player);
Player.main();
return 0;
}
quests.cpp:
#include "quests.h"
#include "player.h"
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
void quests::quest1(player& charact){
cout << "By the way, what was your name?" << endl;
person1=4;
system("pause");
charact->setName();
}
The implementation of your setOtherName function should have the signature
void ClassB::setOtherName(ClassA& cla)
You need to specify that it is included in ClassB. Within your class definition of ClassB, make sure to include
void setOtherName(ClassA&);
Furthermore, since your variable burger is of type ClassA and not of type ClassA*, there is no need to dereference the variable upon passing it into the function. Call it like
fries.setOtherName(burger);
You have also incorrectly dereferenced the variable cla. That object is passed by reference, not pointer, so there is no need to dereference.
You have to read about pointers and reference mate.
This is how your function should look like
void setOtherName(ClassA& cla)
{
cla.setName("foobar");
}
There is no need to deference something that is not a pointer.
ClassA burger;
ClassB fries;
fries.setOtherName(burger);
again, you don't need to dereference burger since its not a pointer.
If burger was created like this:
ClassA* burger = new ClassA();
and the function
void setOtherName(ClassA& cla)
was taking a reference, you had to dereference burger
fries.setOtherName(*burger);
Why are you derefrencing burger? You told the compiler to expect class A by reference, not by pointer.
Try:
fries.setOtherName(burger);
Also, get rid of the asterisk on setOtherName.
void setOtherName(ClassA & cla)
{
cla.setName("foobar");
}
EDIT:
Wrote a sample program of what I think you are trying to do below.
#include <iostream>
#include <string>
class Burger
{
public:
Burger(){}
void setName(std::string name){ m_name = name; }
std::string getName(){ return m_name; }
private:
std::string m_name;
};
class Fries
{
public:
Fries(){}
void setOtherName(Burger & burger){ burger.setName("FryBurger"); }
private:
};
int main()
{
Burger A;
Fries B;
B.setOtherName(A);
std::cout << A.getName() << std::endl;
return 0;
}

A function that returns a queue?

I'm trying to figure out how queues work in C++ and am getting stuck when dealing with objects. I seem to only be able to get a return address instead of the name of the object (which is what I really want). It's also showing an error when I try to pop the element from the queue. My code is as follows:
Buyer.h file
#ifndef BUYER_H
#define BUYER_H
#include <string>
#include <queue>
#include "Order.h"
#include "Entity.h"
#include "Seller.h"
class Order;
class Seller;
class Buyer : public Entity {
public:
Buyer(const std::string &, const std::string &, double);
virtual ~Buyer() { }; // when step is added make this virtual
void addSeller(Seller *);
std::queue<Seller*> getSellers() const;
void addOrder(Order *);
std::queue<Order*> getOrders() const;
virtual void list() const override;
virtual void step() const override;
private:
std::queue<Order*> orders;
std::queue<Seller*> sellers;
};
#endif
Buyer.cpp file
#include <iostream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <queue>
#include "Buyer.h"
#include "Seller.h"
#include "Order.h"
#include "Entity.h"
using namespace std;
Buyer::Buyer(const std::string &name, const std::string &id, double balance)
: Entity(name, id, balance)
{
// initialize seller and order queue??
} // Constructor
void Buyer::addSeller(Seller *s) {
sellers.push(s);
} // addSeller
std::queue<Seller*> Buyer::getSellers() const {
while(!sellers.empty()) {
return sellers;
} // while
} // getSellers
void Buyer::addOrder(Order *o) {
orders.push(o);
} // addOrder
std::queue<Order*> Buyer::getOrders() const {
while(!orders.empty()) {
return orders;
} // while
} // getOrders
void Buyer::list() const {
Entity::list();
std::cout << "Orders:\nOrder contains:";
std::cout << "\nSellers:\n";
int i = 0;
while(!sellers.empty()) {
std::cout << sellers.front() << "\n";
sellers.pop();
} // while
} //list
void Buyer::step() const {
std::cout << "\nstep enter\n"
<< "step exit\n\n";
} // step
Any help is appreciated! Thank you!
(This isn't a full answer but it is too big to go in a comment)
It's OK to return std::queue<Order *>, and so on. However, you need to be clear on who owns the objects being pointed to; i.e. who is responsible for deleting them.
When you return a std::queue<Order *>, what happens is that the returned queue is a copy of the original one, however all the pointers point to the same object that the original one pointed to . (This is a sort of "shallow copy").
If you then delete anything in the returned queue, you will cause the original queue to malfunction because it will be accessing deleted memory.
As such, this is a fragile design because the caller can easily cause the object to screw up despite the fact that getOrders is a const function.
One "solution" is to make the containers contain shared_ptr<Order> instead of Order *. Then everything happens automatically; the caller can add or delete to his heart's content.
If it is not strictly necessary for the containers to contain pointers, consider using containers of objects: std::queue<Order>. The benefit of this approach is that the default copy and move semantics are all correct.
Another approach to consider is having getOrders() and getSellers() return a const reference, instead of returning a copy of the queue.
NB. In Buyer::getSellers(), and getOrders() if it is empty then you fall off the end of the function without returning, causing undefined behaviour. You need to either return something (what's wrong with returning an empty queue?) or throw an exception.