print function vs ostream operator C++

Question:
For printing outputs, do I use ostream& operator<<(){} or a void print(){}?

Note: I am using a class called class_name, and in order to access these private member variables, I need to write public methods that can access private member variables.

Question:
What is the difference between the two following codes ? which one should be implemented ? Or can they both exist and under what condition ?





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ostream operator:
ostream& operator<< (ostream& os, const class_Name& use){
	
	if (use.get_size() == 0){
		os << "{}";
	} 

	else {
		os << "{";
		os << use.get(0);
		for (int i = 0; i < use.get_size(); ++i)
		{
			os << "," << arr.get(i);
		}
		os << "}";
	}
	return os;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
       // print functions:
	void print () const{
		if (size == 0){
			std::cout << "{}";
		}
		else {
			std::cout << "{";
			std::cout << arr[0];
			for (int i = 0; i < size; ++i)
			{
				std::cout << ", " << arr[i];
			}
			std::cout << "}";
		}
	}
        // adds endl if necessary 
	void println(){
		print();
		std::cout << endl;
	}
Last edited on
The first snippet is preferred since it allows the intuitive statement:
1
2
 
  cout << use << endl;


The second snippet is generally used by beginners that have not yet learned to overload the << operator.

Both snippets appear to have the problem of repeating element 0. i.e. Looking at the first snippet, the first element is printed at line 10. The for loop then starts at 0, causing element 0 to be printed again.

Yes, both functions can coexist, but why? Once you've learned to overload the << operator, then is no reason to use the print() function.
Last edited on
printf is far superior to streams for simple tasks. Streams are not wysiwyg due to using variable looking stuff to change modes (setw, for example, looks like a variable and messes up looking at the output in the code). There are times, esp when dealing with just math / floating point output, where printf is cleaner looking code by a long shot.

Streams are superior for object oriented code that overloads << for the class to be printed, among many other things.

You can have both in the same code without any problems.

I use the one that makes the most sense for what I am doing. I am not going to write

std::cout << std::setprecision (15) << std::setw(20) << 3.14159265358979 << std::endl;

to do this

printf("%1.20f", 3.14159265358979);

I refuse. It is idiotic to type that much gibberish to print a number. I understand why they did it, but it looks horrible and its a pain to write when you have 50 values of various precisions and formats.


Yes that was what I was thinking about, both the ostream and print functions can exist, but operator overloading starts to become a better approach when dealing with classes and objects.

@AbstractionAnon, yes :), I am printing zero twice, I should edit int i = 1 instead of 0.

@jonnin, in my class we are learning about object oriented programming using C++, so you recommend to use ostream operator << overloading ? I understand the task is simple now, like printing numbers, but I made it simple, in the future it definitely would be much more complex.

Another question,

for getting size or to print things out I used my object 'use' to do this. Can I make ostream& operator<< a friend function, so I can avoid using getters and setters ?

Some people recommend it if there is no other way around, but there is using getters and setters.
Others try to avoid using friend functions since they access the private variables of the class, and this actions results in the corruption of encapsulation process.

Am I right with my logic?
Last edited on
can't you just overload the << and >> to do it?
Don't see the need to friend it out, but maybe I missed something you said.

Ill stop there, because I disagree with the whole establishment on getters and setters that don't actually do anything else (necessary object manipulations when one items changes another must also type stuff). Its clutter, to me. To others, its necessary handed down from on-high :)
I generally try to make my << stream operator be machine-friendly while my print function is more human readable if the consideration must be made. (personal choice of course)
Last edited on
Have even the smallest bit of abstraction, and using the C stdio functions leads to unreadable, unmaintainable code.

(That is in addition to the fundamental flaw of being thoroughly type-unsafe; a single-character typo in the format string is all that is needed to engender undefined behaviour.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <cstdint>
#include <cinttypes>
#include <cstdio>
#include <iostream>

int main()
{
    // http://en.cppreference.com/w/cpp/header/cstdint
    std::int32_t a ;
    std::int_fast32_t b ;
    std::int_least32_t c ;

    // http://en.cppreference.com/w/cpp/header/cinttypes
    std::scanf( "%" SCNd32 " %" SCNdFAST32 " %" SCNdLEAST32, &a, &b, &c ) ; // decimal
    std::printf( "%" PRId32 " %" PRIdFAST32 " %" PRIdLEAST32 "\n", a, b, c ) ;

    std::cin >> a >> b >> c ;
    std::cout << a << ' ' << b << ' ' << c << '\n' ;
}


Quiz:
Use printf to print out the members of the struct stat, with the code being portable across POSIX implementations.
these system calls return a stat structure, which contains the following fields:

struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
https://linux.die.net/man/2/stat
@JLBorges, I appreciate your time for this code and output, but I don't understand how is this related to operator overloading << or print functions that I provided ?

I would appreciate some clarification, so I can relate this to my own problem and understand what is going on.


Thank you everyone else who gave their feed back for the codes.
Last edited on
> how is this related to operator overloading << or print functions that I provided ?

This is not related to operator overloading << or print functions that you provided ?

This was in response to the claim: 'printf is far superior to streams for simple tasks.'
Essentially, the point I was making is that a whole bunch of tasks that are very simple if C++ streams are used become complex, ugly and brittle if C stdio functions are used instead.


Re. the question that you posed:

For an output streamable type not designed for inheritance, I favour overloading the << operator.
You may want to skip this for now: typically as an inline friend function (does not pollute the containing namespace; but transparently accessible via ADL).

For an output streamable polymorphic type, I tend to do both:
1
2
3
4
5
6
7
8
9
10
11
12
struct A // designed for inheritance
{
    virtual ~A() ; 
    // etc.

    virtual std::ostream& print( std::ostream& stm ) const ;

    // ...
};

// polymorphic stream insertion operator (all that a derived class has to do is override print)
inline std::ostream& operator<< ( std::ostream& stm, const A& object ) { return object.print(stm) ; }
Topic archived. No new replies allowed.