0

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;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
agile_flow
  • 58
  • 7
  • 1
    "Picture not uploading" -- hooray! Finally, no more utterly worthless, and useless pictures on Stackoverflow, they finally banned them!! You can always upload your pictures to Facebook or Twitter, where they belong, while Stackoverflow contains only questions that get asked in plain text, so they can be easily copy-pasted for further research. P.S.: it sounds like your C++ textbook is horrible. It doesn't even use the correct C++ terminology. It's "class member" instead of "attribute". What C++ textbook did you read this terminology from? – Sam Varshavchik Jan 19 '23 at 20:49
  • Why are you using pointers for this assignment? Nothing suggests usage of pointers, and especially `void` pointers. Then `this->humanBrain = new Brain;` -- this couldn't have compiled, since `humanBrain` is not a pointer. – PaulMcKenzie Jan 19 '23 at 20:50
  • @SamVarshavchik • did they really **ban** them? I thought the poster just needed sufficient rep. Enough rep to know better than to post one. – Eljay Jan 19 '23 at 20:51
  • `Brain b = this->humanBrain.identify();`: (1) Why are you trying to initialize an instance of `Brain` with a `std::string` argument? This makes no sense. Fix that before moving any further. (2) Drop `this->`; it’s redundant in that context. – Andrej Podzimek Jan 19 '23 at 20:52
  • 1
    I can only hope, @Eljay... Besides, there's plenty of misdirected Facebook cat pictures uploads here, from 1 rep users... – Sam Varshavchik Jan 19 '23 at 20:54
  • A hint: `std::string Human::identify() const { return humanBrain.identify(); }` How hard can it be? – Andrej Podzimek Jan 19 '23 at 20:54
  • Another hint: [`std::hex`](https://en.cppreference.com/w/cpp/io/manip/hex) – Andrej Podzimek Jan 19 '23 at 20:56
  • 1
    @AndrejPodzimek no need for `std::hex` since `operator<<` prints pointers in hex. `std::hex` only applies to integers – Remy Lebeau Jan 19 '23 at 21:05
  • @AndrejPodzimek Ok, so can you explain to me why moving "const" to AFTER the function declaration (at the end) allowed me to access the Identify on the member humanBrain? And when I create getBrain here, it returns a different address than the bob.identify. Why? Brain(Human::getBrain() const) { return this->humanBrain; } – – agile_flow Jan 19 '23 at 21:10
  • @PaulMcKenzie yes it didn't compile-- I had humanBrain as a pointer initially, and it did at the time. But in the process of figuring this problem out, I changed it. And while yes the problem doesn't explicitly mention pointers, the problem set is titled "Memory allocation, References, Pointers to members, File streams". And one of the earlier problems was using pointers. – agile_flow Jan 19 '23 at 21:15
  • 1
    @agile_flow I address the `const` issue in my answer. You should have lead with that in your question, ie by providing the actual error you were getting. As for the `getBrain()` issue, you are returning the `Brain` object *by value*, thus you are returning a *copy* of the `humanBrain` member. You need to return it *by reference* instead, as I also showed in my answer. – Remy Lebeau Jan 19 '23 at 21:20

1 Answers1

0

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();
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Ok, so can you explain to me why moving "const" to AFTER the function declaration (at the end) allowed me to access the Identify on the member humanBrain? And when I create getBrain here, it returns a different address than the bob.identify. Why? Brain(Human::getBrain() const) { return this->humanBrain; } – agile_flow Jan 19 '23 at 21:06
  • @agile_flow I updated my answer to address the `const` issue. You should have lead with that in your question, ie by providing the actual error you were getting. As for the `getBrain()` issue, you are returning the `Brain` object *by value*, thus you are returning a *copy* of the `humanBrain` member. You need to return it *by reference* instead, as I showed in my answer. – Remy Lebeau Jan 19 '23 at 21:14
  • thank you. I was getting confused to where the const actually binded to. Good catch on the "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." I didn't understand that but I do now. Going forward, what would you say would be my best learning resource in this area? I understand passing by value and reference, but being wrapped up in a bigger example here confuses me sometimes. – agile_flow Jan 19 '23 at 21:28
  • 1
    @agile_flow "*Going forward, what would you say would be my best learning resource in this area?*" - to stop learning from random online examples, and instead to get yourself some [good C++ books](https://stackoverflow.com/questions/388242/). – Remy Lebeau Jan 19 '23 at 21:36