Pointer not returning the way I was expecting to

I have decided to overload the builtin 'string' class and create my own custom String class in order to improve my knowledge regarding operators overloading in C++. Below is my written class included in '__LIB' namespace:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
namespace __LIB
{
    ////////////////////////////
    class String
    {
        // Constants.
        static const short int M_SIZE = 1024;
        
        // Vars.
        char string[M_SIZE];
        
        // Get length of str[]
        short int __getLength(char str[]) {
            short int length = 0;
            
            for(short int i = 0; i < MAX_SIZE; i++)
            {
                if(str[i] != '\0')
                    length++;
                else
                    return ++length;
            }
        }
        
        public:
            // Constants.
            static const short int MAX_SIZE = String::M_SIZE;
            
            void operator=(char str[]) {
                short int length = this -> __getLength(str);
                
                for(short int i = 0; i < length; i++)
                    this -> string[i] = str[i];
            }
            
            friend char* operator<<(std::ostream &, String &);
            //friend std::ostream& operator<<(std::ostream &, String &);
            
            String(char str[]) {
                this -> operator=(str);    
            }
            ~String(){}
    };
    ////////////////////////////
    
    // The following method works 100%
    /*std::ostream& operator<<(std::ostream &ostream_object, String &string_object)
    {
        return ostream_object << string_object.string;
    }*/
    
    // ..however the following one doesn't. Why?
    char* operator<<(std::ostream &ostream_object, String &string_object) {
        return string_object.string;
    }
    
}


Below is the code I have written in order to test the functionality of my class:

1
2
3
4
5
6
7
8
9
10
int main()
{
    String alex = "11252wwd";
    
    std::cout << alex;
    
    int i; std::cin >> i;
    
    return 0;    
}


For some reasons, the line 'std::cout << alex;' outputs nothing, while it should output '11252wwd'. The generic OStream operator '<<' is overloaded in the last function from '__LIB' namespace. The function is declared as 'friend' inside 'String' class. 'String::string' is declared as a 'char' array.

Why does line 'std::cout << alex;' outputs nothing?
operator<< doesn't write anything to ostream_object.
Yeah, terioo, you should be returning the stream. Your function *could* work, technically, but not in a convenient way. You could realize that, as written, the friend function returns a pointer to a character array, and if you assigned something to that return, the value could be retrieved (I also added some const where needed):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>

class String
{
    // Constants.
    static const short int M_SIZE = 1024;
    
    // Vars.
    char string[M_SIZE];
    
    // Get length of str[]
    short int __getLength(const char str[]) {
        short int length = 0;
        
        for(short int i = 0; i < MAX_SIZE; i++)
        {
            if(str[i] != '\0')
                length++;
            else
                return ++length;
        }
        return length;
    }
    
    public:
        // Constants.
        static const short int MAX_SIZE = String::M_SIZE;
        
        void operator=(const char str[]) {
            short int length = this -> __getLength(str);
            
            for(short int i = 0; i < length; i++)
                this -> string[i] = str[i];
        }

        // Does not work as you expect -- incorrectly fails to return a stream
        friend const char* operator<<(std::ostream&, const String&);
        
        String(const char str[]) {
            this -> operator=(str);    
        }
        ~String(){}
};

const char* operator<<(std::ostream& ostream_object, const String& string_object) {
    return string_object.string;
}

int main()
{
    String alex = "11252wwd";
    
    const char* test = std::cout << alex;   // Very awkward
    std::cout << test << '\n';
    
    return 0; 
}


A simple example of the more convenient stream friendship:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

class Cell
{
public:
    Cell() {}
    Cell(int x, int y) : x(x), y(y) {}

    friend ostream& operator<<(ostream& os, const Cell& c)
    {
        os << "(" << c.x << ", " << c.y << ")";
        return os;
    }
    friend istream& operator>>(istream& is, Cell& c)
    {
        is >> c.x >> c.y;
        return is;
    }

private:
    int x;
    int y;
};


Side note: don't get into habit of starting any variable names with underscores -- these are usually reserved. Append an underscore if you'd like, as often seen to mark private variables.
Last edited on
Thank you very much for your replies!

I did not understand however (considering my second posted code) why std::cout << alex does not output the characters from returned starting pointer directly. I bring into argument the following code which I have just tested and it's working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

char* func()
{
    char* pChar = new char[1024];
    pChar = "123456789";
    
    return pChar;
}

int main()
{
    std::cout << func();

    return 0;
}


In my mind func() is a relative equivalent of the exact same procedures which are happening between friend operator<<() and String class from my initial posted code. Why on this case std::cout from main() outputs the characters correctly, while on original case it outputs nothing?

---------------------------------

I know I should be returning an OStream object so that std::cout from main() will handle the returned OStream object and print everything out, but since I bumped into this issue I want to learn from it before I move one. Thank you for baring with me.
You're misunderstanding what << and the operator overload do.

Forget for a moment the << syntax. Let's write a straightforward output function.
1
2
3
4
5
void print(std::ostream &stream, String &s) {
    stream << s.string;
}

print(std::cout, string_object);
I think this is straightforward enough that it doesn't need commenting.

What if we rename print to something else?
1
2
3
4
5
void operator<<(std::ostream &stream, String &s) {
    stream << s.string;
}

operator<<(std::cout, string_object);
(Note: I'm unsure if this is syntactically valid. This is just an explanation.)

Or, after adding some syntactic sugar:
1
2
3
4
5
void operator<<(std::ostream &stream, String &s) {
    stream << s.string;
}

std::cout << string_object;

Does this make it clearer what's happening?
Yes it does. However I still don't get it :(

1
2
3
4
5
6
7
8
    char* operator<<(std::ostream &o, String &s) {
        o << s.string; // This one prints s.string
        return s.string; 
    } // I return a pointer to the first character from array, where array is 's.string'.

    [...]

    std::cout << object; // This one prints nothing 


1
2
3
4
5
6
7
8
    std::ostream& operator<<(std::ostream &o, String &s) {
        o << s.string; // This one prints s.string
        return s.string;
    } // I return an OStream object

    [...]

    std::cout << object; // This one prints s.string as well! 


That ^ is what I don't understand. Why first case doesn't print the characters at std::cout << object; considering the fact that I have returned a pointer to string array?

If I'm missing anything please guide me to some useful resources.
What you return from the overload has no effect on what the overload does. The usual pattern for output operator<<() overloads is to return a reference to the left-hand-side operand to enable chaining. std::cout << foo << bar really means (std::cout << foo) << bar, which, if the overload returns the LHS operand, is equivalent to
1
2
std::cout << foo;
std::cout << bar;
But the overload haven't have to return the LHS operand. If this overload returns some random thing, std::cout << foo << bar may not compile, or it may have different semantics to writing two separate statements (actually, this can sometimes be useful to achieve specific effects).

Your second snippet should not compile. Your first snippet should print the contents of the string, but you won't be able to do std::cout << object << "my string", because you can't send output to a 'char *'.
I don't know what your comments on lines 2 and 8 mean.
operator<< returns the ostream& so that it can be "chained".

1
2
3
4
5
6
7
8
9
#include <iostream>

int main() {
    // This:
    std::cout << '1' << '2' << '3' << '\n';

    // means this:
    operator<<(operator<<(operator<<(operator<<(std::cout, '1'), '2'), '3'), '\n');
}
Your second snippet should not compile.

It does. I've just checked it. I use DevC++. It outputs the content of s.string twice.

Your first snippet should print the contents of the string

It prints the content only once, when line 2 is hit.

I don't know what your comments on lines 2 and 8 mean.

I wasn't very clear at the beginning, so I re-wrote them. When I say This line prints xyz it means that if I remove that line from entire code, xyz will not be printed anymore, for that single line declaration.

1
2
3
4
5
6
7
8
9
10
11
    char* operator<<(std::ostream &o, String &s) {
        o << s.string; // This line prints the content of s.string
        return s.string; 
    } // I return a pointer to the first character from array, where array is 's.string'.

    [...]

    std::cout << object; // This line prints nothing. Literally nothing.

// In the end, this snipped outputs to screen the content of s.string once. 
// If s.string = '123abc' then the output is '123abc' 


1
2
3
4
5
6
7
8
9
10
11
    std::ostream& operator<<(std::ostream &o, String &s) {
        o << s.string; // This line prints the content of s.string
        return s.string;
    } // I return an OStream object

    [...]

    std::cout << object; // This line prints the content of s.string as well!

// In the end, this snipped outputs to screen the content of s.string twice. 
// If s.string = '123abc' then the output is '123abc123abc' 

Last edited on
It does. I've just checked it. I use DevC++. It outputs the content of s.string twice.
It shouldn't compile. You're returning a char[] from a function that's supposed to return an std::ostream &. It's an impossible conversion. This:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

class A{
};

static char static_string[] = "hello";

std::ostream &operator<<(std::ostream &stream, const A &){
    return static_string;
}

int main(){
    std::cout << A();
}
is rejected by GCC 6.3.0 with the error
cout_test.cpp: In function 'std::ostream& operator<<(std::ostream&, const A&)':
cout_test.cpp:9:12: error: invalid initialization of reference of type 'std::ostream& {aka std::basic_ostream<char>&}' from expression of type 'char [6]'


Either you've omitted some critical detail, or the compiler that Dev-C++ uses has some serious issues.
Last edited on
You are right. I forgot to change s.string with o << s.string when I wrote the code in forum editor. But still, this does not help me understand the original issue: why first snippet prints content of s.string once while second snippet prints it twice? Or in other words: why on first snippet, line 8 does not print the characters from s.string even if I returned a char pointer to the first element of s.string?

1
2
3
4
5
6
7
8
9
10
11
char* operator<<(std::ostream &o, String &s) {
    o << s.string; // This line prints the content of s.string
    return s.string; 
} // I return a pointer to the first character from array, where array is 's.string'.

[...]

std::cout << object; // This line prints nothing. Literally nothing.

// In the end, this snipped outputs to screen the content of s.string once. 
// If s.string = '123abc' then the output is '123abc'  


1
2
3
4
5
6
7
8
9
10
11
std::ostream& operator<<(std::ostream &o, String &s) {
    o << s.string; // This line prints the content of s.string
    return o << s.string;
} // I return an OStream object

[...]

std::cout << object; // This line prints the content of s.string as well!

// In the end, this snipped outputs to screen the content of s.string twice. 
// If s.string = '123abc' then the output is '123abc123abc'  


1
2
3
4
std::ostream& operator<<(std::ostream &o, String &s) {
    o << s.string; // first output
    return o << s.string; // second output
}
Thank you very much for all your replies! I now understand how things work!
Topic archived. No new replies allowed.