C++ Questions

Pages: 123456... 13
SubZeroWins wrote:
Have you guys used the timing in the 1st link yet and as I copied into my code? Is this something you know by memory or do you need to reference it?

For tests that I'm just going to throw away afterwards I often use a function from another library that gives me the time in milliseconds because it's much easier. I don't know std::chrono by heart so if I use that I will have to copy it from somewhere.

Be careful with jumping to conclusions when measuring performance on small test programs. There are many mistakes that you can make. Here are some advice and things that are good to know.

★ Make sure to enable compiler optimizations (and disable "debug mode") because you probably don't care too much about the performance of an unoptimized build.

★ Timings can often fluctuate quite a bit so make sure it runs for long enough for the times to be useful. Repeat to see that it is consistent.

★ Make sure the result is actually used afterwards so that it is not optimized away. Assigning the result to a volatile variable is a simple trick to avoid the compiler from optimizing away the result.

★ If you run the same code inside a loop multiple times to make the measurements take longer you need to be careful that the compiler will not optimize away the loop. (In your code the compiler will most probably optimize away the whole loop; See https://godbolt.org/z/oEWorWW5W )

★ The compiler can often do very aggressive optimizations if it knows the input values. In a real program the inputs are often not known (they might vary depending on various factors or just be harder for the compiler to see for various reasons). To account for that you might want to randomize the input or use other techniques (e.g. volatile) to avoid that the compiler optimizes the code based on specific input values.

★ Things often gets "warmed up" and performs faster the second time or after a while. E.g. things gets loaded into memory and stored in caches (this is true for file IO and recently used RAM) and the CPU "learns" the outcome of loop and if conditions which also makes things faster. If you're measuring two pieces of code inside the same program the first one might be slower just because it's first and things have not got "warmed up" yet. This can have a quite big impact on the measurements.

★ It's usually best if you can measure the performance in the real program that you are interested in (or in a situation that is as similar to how it will be used in the real program as possible) because, as you saw above, there are many factors that can affect the timings and smaller tests might not be representative for how it will perform in the real program.
Last edited on
TheIdeasMan, thanks that was beautiful and I now prefer this RAII (Resource Acquisition Is Initialization) method of handling chronos timing with the natural usage of the constructor/destructor. It flows so well!

Peter, oh yes I see that it can optimize the while loop away. I would love to also learn assembly some day to help better learn/utilize c++. That is an extensive list, thanks!

I had this cloud over me, even when deciding to add, for instance, the "count" inside the statements or outside. I know certain variations can make all the difference, but I wanted to see if it made a difference when balancing if/else with the switch and with another test with no statements in main(). I thought there would be a bigger difference there. Though, something like adding a "\n" vs endl can make a big difference though in timing and there is much to be weary of.

This next one has also been lurking around for me since I first read about inheritance.
8) The business of "is a" vs "has a".

"is a": implies a public inheritance between base/derived
mammal->human, lion, seal
fish->bass, trout, perch
fruit->apple, orange, kiwi

"has a": implies a private or protected inheritance between base/derived
motor->Toyota, Ford, Audi
network card->pc, phone, laptop
door->car, house, mobile home

So now if you choose mammal->human, are you forced into using the "public" access specifier and you should NEVER use private or protected because in reality they really are in a "is a" relationship?

Can someone say, although that relationship is true I still choose to make the inheritance private or protected because I don't want anyone touching certain aspects of base from main()? I also understand that you can make member attributes in base as private/protected as well and as needed.
But what if I just made a "is a" relationship with an inheritance of private or protected anyways, would programmers generally have issues with this and is this considered bad coding practice? Or will they say ehhh, it does not matter?
SubZeroWins wrote:
I would love to also learn assembly some day to help better learn/utilize c++.

C++ programmers usually don't need to know assembly. A basic understanding of assembly can be useful if you want to analyze compiler optimizations with Compiler Explorer but for the link that I provided you don't need to know anything. My point was just to show that it generated the exact same instructions for all three functions.

SubZeroWins wrote:
I had this cloud over me, even when deciding to add, for instance, the "count" inside the statements or outside. I know certain variations can make all the difference, but I wanted to see if it made a difference when balancing if/else with the switch and with another test with no statements in main(). I thought there would be a bigger difference there. Though, something like adding a "\n" vs endl can make a big difference though in timing and there is much to be weary of.

Don't worry too much. A lot of things will get optimized and even if it's not optimal it's often "good enough". Even the use of endl is unlikely to be the bottleneck unless you do a lot of file IO or something.

There is this saying that "90% of the time is spent in 10% of the code". So it might be worth spending your effort optimizing the 10% that really matters, e.g. tight loops. Profilers can help you find where your program spends most of its time. In the remaining 90% of the code it might be better to focus more on keeping things simple and readable.

SubZeroWins wrote:
8) The business of "is a" vs "has a".

"is a" - public inheritence - a lion is a mammal

"has a" - this usually implies the use of member variables - a house has a door

I'm not sure exactly how private inheritance fits into the OOP concepts above. I don't think I have ever used private inheritance.
Last edited on
Hi,

There is a third relationship: "Uses A"

This is where an argument to a class constructor or function is of a different type: Class RaceCar has a function which has an argument RaceEvent. So RaceCar uses RaceEvent. This example would probably use a Design Pattern such as Observer (aka Publisher / Subscriber) .

https://stackoverflow.com/questions/9226479/mediator-vs-observer-object-oriented-design-patterns

There are lots of Design Patterns, and they can be combined.

The concepts of inheritance, composition etc and the design of the code, is whole subject of it's own. It is not as easy as one might first expect. A lot of people might think: "Oh yeah, I will have these classes with these members and functions". But that is not the case; one has to be quite careful to design the code correctly. Things to avoid are: Large inheritance trees; tight coupling.

Here is some more stuff to read:

https://en.wikipedia.org/wiki/SOLID
https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)

Good Luck !!

No, I understand the is a/has a relationship of the list I created in the real world. What I was asking is this:

1
2
3
class Mammal{};

class Lion:public Mammal{};


The relationship between Mammal and Lion is "is a", which means it implies a public inheritance between base Mammal and derived Lion. BUT, although the relationship is "is a" what if I decide to make the inheritance private or protected,

1
2
3
class Mammal{};

class Lion:protected Mammal{};


1
2
3
class Mammal{};

class Lion:private Mammal{};


because I simply don't want users to touch the base class from main() for whatever reason.
Again, I also understand that I can make member variables and methods in base/derived class private/protected as needed in order to keep away from public access from main().

So although the relationship is in a "is a" relationship, that I intentionally made the inheritance protected or private. Will that be a red flag to someone and will they say what in the world are you doing, that is supposed to be a "is a" relationship and that should NEVER be in a private or protected relationship. Is it BAD coding to make that public inheritance change to protected or private?

Once I change the inheritance to protected or private, I no longer make the "is a" relationship between Mammal and Lion and the relationship becomes "has a" in THEORY. The Lion "is a" no longer a mammal then. And even though the code will work perfectly fine and I will fulfill my desire to not have users/newbies access and modify members of class base from main().


There is a third relationship: "Uses A"

I have not read anything about a 3rd relationship ("Uses A"), but that sure sounds a lot like an example the book gave. A Car class that inherits from Motor class can have a bottleneck in today's world where we have electric motors, so the solution was to use composition/aggregation to include an ElectricMotor within the class as a member. No mention of "Uses A" though.

So then, of course my brain runs wild and thinks well then we really can't predict many things in future advances. We can use a pig to grow a modified human heart and it can grow multiple organs of sorts. Humans might have quantum brains or specialized limbs appended. So why not just make many things or everything aggregation then.
Last edited on
Abstract classes.

https://en.cppreference.com/w/cpp/language/abstract_class

I can see having a base class not being instantiated. Denying someone from instantiating a derived class is rather useless, otherwise why bother using class inheritance.
Peter, I did understand that the code is EXACT duplicates from the assembly code and your comments section when I first saw it. Still I would love to be able to understand the syntax as it might come in handy one day. No rush to look at it now though.

What other languages do you know besides C++, let me guess Python?

I also know that I should be using std::, I know George hates it, but I transcribe my code samples and notes in a document and I will print it out, multiple times with modifications. So much wasted ink in typing all that and I can move on with practicing sample code much quicker when not using std:: for now. I will make that transition when doing a real project.

I had finally read the Smart Pointer chapter, and to be honest I was disappointed. It provided insight as to how the various smart pointer types (deep copy, COW, reference counted, reference linked, and destructive copy) work behind the scenes. Great insight into them, but I can't do anything immediately. I did not know that the copy constructor and assignment operator were private for the unique_ptr and that you cannot pass it by val to a func, only by ref.., based on initial code I saw before reading this chapter.

9)What smart pointers do you see most often used, and what are the most popular pointers out there, the ones from the Boost library? Are 90% of the times just good enough for the unique_ptr and is that what you experience?

I have also read the exception handling (EH) chapter.

10) Do you also include EH in built-in types, such as int/bool/char in a release program? Another way to look at it is, if the system has that few resources you then have bigger problems and there is no need to weight down your already burdened program (that may perform some critical and resource intensive tasks) with more EH's? Or is the answer no way, wherever there can be an exception, handle it, even if it is as small as a bool or char?
George, how is this preventing instantiating of derived? You can still instantiate derived, but won't have access to base from main() as it is protected or private inheritance. With some applications this scenario won't make sense, but with others it will.

Lets say I am using base as a really important mission critical part in another inheritance and I don't want to give the user access to base from main() for the Mammal->Lion inheritance. So I made something that should really be in an "is a" relationship (and should be public), into private or protected. After all, it can be done and the code will work, but is it WRONG?

1
2
3
class Mammal{};

class Lion:protected Mammal{};


1
2
3
class Mammal{};

class Lion:private Mammal{};


You can tell me:
A) No, never make anything that is supposed to be in a "is a" relationship private or protected. ONLY USE PUBLIC INHERITANCE....ALWAYS!!!! Just change the members as private/protected as needed.

B) Or as long as the code works, it does not matter?

Will that change trigger eyebrows?
Protected/private inheritance is all about what access the derived class(s) has to the protected/public members of the base class. See:

https://en.cppreference.com/w/cpp/language/derived_class
https://www.learncpp.com/cpp-tutorial/inheritance-and-access-specifiers
I understand that, BUT it also influences what members of base can be accessed DIRECTLY from main() as well. Protected/private base (Mammal) inheritance on derived (Lion) means you no longer have access to base members from main(), EVEN if the members in base are public. And it also changes the coding theoretical relationship from "is a" to "has a".

 
class Lion:protected Mammal{};

I also understand that when you make that protected, only derived classes of base can have access to public and protected members of base (from derived in main()). No main() access directly to base.

 
class Lion:private Mammal{};

I also understand that when you make that private, only the direct derived class has access to public/protected base members (from within the derived class only). No main() access directly to base.

Because I can really change the inheritance of Mammal to private or protected in code, which then changes the relationship between the 2 and the book's theory on this, is it wrong and just bad coding practice? I just made something that should be in a "is a" relationship into something that is in a "has a" relationship and that is just wrong? Or can it just be done and no programmer will throw a tantrum?
Last edited on
SubZeroWins wrote:
What other languages do you know besides C++, let me guess Python?

In school we mostly used Java so that is the language apart from C++ that I have most experience with. I also know JavaScript and PHP. Then there are other languages that I have only used a little or a long time ago.

I can understand simple Python code because I have experience with other languages and I know how to look things up, I have even helped answering a few beginner Python questions on other forums, but I have never actually tried to learn Python or used it for anything so I wouldn't say I "know" it.

After programming for a while and learning a few languages you realize that there is a lot of similarity between them. Learning a new language is much easier when you already have experience with other languages.

SubZeroWins wrote:
Lets say I am using base as a really important mission critical part in another inheritance and I don't want to give the user access to base from main() for the Mammal->Lion inheritance.

The question is why do you use inheritance in this situation? Private inheritance is essentially an implementation detail. It doesn't affect the code outside the class. From outside the class the Lion would not be seen (and usable) as a Mammal.

SubZeroWins wrote:
So I made something that should really be in an "is a" relationship (and should be public), into private or protected.

If it "should be", as you said, then you should probably use public inheritance. Note that many languages like Java and C# don't even have private inheritance (only public inheritance).

SubZeroWins wrote:
After all, it can be done and the code will work, but is it WRONG?

If you have a reason for doing it then it's not necessarily wrong otherwise my advice is to just ignore private inheritance as an option.

There is an OOP principle that says "Prefer composition over inheritance" which essentially means you should prefer to use member variables instead of inheritance.

https://en.wikipedia.org/wiki/Composition_over_inheritance
classes should favor polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) over inheritance from a base

https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-domain
Do not use inheritance when simply having a data member will do.


SubZeroWins wrote:
A) No, never make anything that is supposed to be in a "is a" relationship private or protected. ONLY USE PUBLIC INHERITANCE....ALWAYS!!!!

I'm normally a bit allergic to rules that says never/always but this sounds pretty good to me.
Last edited on
SubZeroWins wrote:
10) Do you also include EH in built-in types, such as int/bool/char in a release program?

Do you mean throwing those types? I usually only throw types derived from std::exception although in some limited parts of my projects I have also sometimes thrown enums but only of types that I have specifically defined for this purpose (usually with Exception or Error in the name). Throwing int, bool or char doesn't make sense to me because the type doesn't signify what it means and why you would want to catch it.

I catch exception where it makes sense, especially in release because that is when I want to recover or at least show a nice error message to the user. It is while debugging it can be more convenient to not catch the exception in order to get a stack trace from the debugger.
Last edited on
SubZeroWins wrote:
I have not read anything about a 3rd relationship ("Uses A"), but that sure sounds a lot like an example the book gave. A Car class that inherits from Motor class can have a bottleneck in today's world where we have electric motors, so the solution was to use composition/aggregation to include an ElectricMotor within the class as a member. No mention of "Uses A" though.


https://www.learncpp.com/cpp-tutorial/association/


A Car class would not inherit from a Motor class. A Car "HAS A" Motor, so the Car class would have a member of type Motor. With regard to electric motors, I would have a Base class Motor, then subclasses Electric and Piston. The Car class could then have a member std::unique_ptr<Motor> , which is initialised to a pointer to Electric or Piston. See next paragraph. I have used unique_ptr here, but it could be shared_ptr if motors, transmissions, wheels etc could be used in other cars.

This brings me to another important concept: Generic naming / polymorphism.

Notice I didn't have classes named ElectricMotor and PetrolMotor , and the member variable is a (smart ) pointer or reference to Motor which would be an abstract base class. Here is the big concept: A pointer or reference to a Derived class is a valid pointer or reference to a Base class. This allows the use of polymorphism, which means that the correct derived class functionality is implemented. Because the Car class has a pointer to Motor, it can be initialised with any kind of derived Motor, which makes things much easier.

https://cplusplus.com/doc/tutorial/polymorphism/

cplusplustutorial wrote:
Pointers to base class

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature.


SubZeroWins wrote:
And it also changes the coding theoretical relationship from "is a" to "has a".


Just changing the inheritance from public to protected or private and then not having member variables of the other types, sounds weird to me.
8) I've got my answer now, thanks guys!

The example relationships that I provided are quite straightforward, but sometimes it is not quite clear and the lines might get blurred between "is a" & "has a". When I am doing inheritance now for practice I do them all sorts of ways at times for practice and to see the limits, and most other times I too just use public for ease of access and testing. I will have to get into the habit of more restrictive access as time goes on and to write some real world code.

Someone who never codes with others or does not share code can go on an entire lifetime without ever using private/protected, at the risk of making unintentional mistakes of course.

Design Patterns sounds like a must have eventually too after I get this newer stuff straightened out.

A Car class would not inherit from a Motor class

The book did have a code where Motor was inherited by car, by regular inheritance. Then in another section they mentioned future problems as a note and the composition solution as a partial snippet. But I do understand when you have composition that it is not inheritance, but simply "has a"...has the composition of the Motor class and hence "has a" motor.

I've also seen a wild example of polymorphism where a base* was used to clone derived* on the heap, wild stuff but it works. One of the inherent beauties of pointers in polymorphism.
Do you mean throwing those types?

Yes, exactly that.


More on inheritance: http://www.gotw.ca/publications/mill06.htm
Example 2(a), Derived was responsible for both customizing Base and implementing itself in terms of Base. In Example 2(b), those concerns are nicely separated out.


Well, that was a very detailed and interesting read! Can't say I can keep track of all these combos in my head (variations of inheritance vs composition) just yet and I will re-read the article again, but very insightful! So from what you have seen, are programmers using more composition nowadays where applicable?

Thanks for all your help fellas, you guys have been very helpful!

1
2
3
4
5
6
7
8
9
10
11
	int i = 0;
	do
	{
		cout << "Num to find: ";
		//int i =0;		//NOT WORK INSIDE OF LOOP!!!!!!!
		cin >> i;

		if (ms1.count(i) == 0)
			cout << i << " NOT FOUND TRY AGAIN..." << endl;

	} while (ms1.count(i) == 0);


11) NOTE: I found it interesting that the declaration of the variable INSIDE the while loop is not allowed. Although, if it did work it shouldn't be a problem for THIS particular code for a multiset since the 0 value would be overwritten by the user input. In other general circumstances, the loop would iterate and the variable "i" would reset to 0 with each iteration and this would not be ideal, and hence the declaration for the boolean test inside the while() loop is not allowed and is required to be outside the loop.

QUESTION: Is there a slick way to combine the if test with the while() boolean test, something like the line below that does not work completely? Something that requires no additional checking or testing? It would be nice if the while() loop had this... run this line, which only happens once the loop goes through its very first iteration.

 
//} while (msetInts.count(i) == 0,cout << "NOT FOUND TRY AGAIN..."); 


1
2
3
4
	for (;;)
	{
		int aNum = 3;
	}

This code above declares and creates the variable only ONCE, and then thereafter indefinitely sets it to 3, right? I also understand that the compiler might optimize this away and do something like set it as a constexpr to 3.
If i was declared inside the loop it would go out of scope at the } on line 11 which is why you cannot access it outside in the loop condition.
Last edited on
The while() bool check, although is part of the loop, is considered to be outside the block code...and there is no inference the compiler has to include it as part to the block...that part is understood!

They could have programmed this alternatively though, but there is no logical reason to reset a declared variable inside the loop and so it was forced to be declared outside.
you can do it, of course. Its just... not much 'better'.
1
2
3
4
5
6
for(bool b= false; !b;)
{
     do first time stuff;
     if(acceptable) b = true;
}


you can also just scope what you have:
1
2
3
4
5
{
  int i{0}
  do
 ...
}//i dies HERE 
//this is extra anal retentive, but ... you asked. it prevents accidental corruption of the commonly reused i variable name. You rarely see this for just an int, but you will see it for objects that need to die or else bad things happen, so they kill it by extra bracket scoping
Last edited on
Pages: 123456... 13