• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C++ off hand questions - Stumped

cabri

Diamond Member
Stumbled upon these doing a review of new hire questions from (2000) and am stumped; never worried about these situations.
Are they real world or just hypothetical - my C++ training is not academic?


Generic version of the max function, for use with most any data type
Where types can be morphed, how is this really possible/practical 😕



Class A { };
Class B1 : public A { };
Class B2 : public A { };
Class C : public B1, public B2 { };


B1 inherits a virtual public A, and B2 inherits a virtual private A! What access rights does C have to A’s members?
Why would this be and what would be the benefit. I have always felt that when you get too fancy, it becomes hard to understand the resulting concept
 
Last edited:
First one is a template method. Find the max for floats, ints, complex, etc. Very useful.

Second could be A = animal, B1 = mammal, B2 = wingedAnimal, C = bat. Pretty typical academic setup for learning about inheritance.
 
Understand the template issue. The way I read the question was a one size for all solution.

The split between private access to me indicates no access to A. But with a second inheritance being public, i can not wrap my self on how which is valid. I would think thst the A publics are accessible.
 
Understand the template issue. The way I read the question was a one size for all solution.
I think it's implied that the data types used in this function must overload the comparison operators. Otherwise there's no consistent definition of "maximum".

I'm not sure what's going on with the second one. The keyword "private" does not appear in your class definitions. 😕
 
Because both inheritance levels are public, C has full access to A's members.

A slight complication arises as C has inherited A twice, and may result in needs to distinguishing between B1::A and B2::A.
 
The inheritance example is the "dreaded diamond" sometimes known as the "diamond of death". If you don't use virtual inheritance, C ends up with two copies of A's fields, one copy for B1 and another for B2. If you do use virtual inheritance, you avoid the field duplication, but I don't remember off the top of my head how that works since B1 and B2 may both be making conflicting changes to the state of A. Realistically you should almost never use that kind of inheritance because even if you get it to work correctly, it's confusing and fragile when other people start coming in to change it. There are almost always better solutions via either implementing interfaces (Abstract Base Classes in C++ jargon) or using composition over inheritance (e.g. the strategy pattern).

Edit: Also, the dreaded diamond is one of the reasons that a great many languages outright ban multiple inheritance.
 
A slight complication arises as C has inherited A twice, and may result in needs to distinguishing between B1::A and B2::A.

It won't compile and run, and for that reason. I just tested it and got an "ambiguous error" for anything I tried to define in A. Understandably so too. Because even though in this case anything you declare is duplicate and could just be merged, if you were to use that same code and combine two different classes, but with say the same "int i" defined and assigned different values in its respective class, how does the compiler know which one to pick?
 
Last edited:
(I will not address the accessibility question.)

The non-virtual diamond:
Code:
#include <iostream>

struct A
{
    int x;
    A( int y ) : x(y) {
        std::cout << "A::A(" << y << ")\n";
    }
};

struct B1 : public A
{
    B1() : A(7) {
        std::cout << "B1::B1()\n";
    }
};

struct B2 : public A
{
    B2() : A(42) {
        std::cout << "B2::B2()\n";
    }
};

struct C : public B1, public B2
{
    C() : B1(), B2() {
        std::cout << "C::C()\n";
    }
};

int main()
{
    C foo;
    // std::cout << "Hello, " << foo.x << '\n'; // error: ambiguous
    std::cout << "Hello, " << foo.B1::x << '\n';
    std::cout << "Hello, " << foo.B2::x << '\n';
    std::cout << sizeof(foo) << '\n';
    return 0;
}
Output:
A::A(7)
B1::B1()
A::A(42)
B2::B2()
C::C()
Hello, 7
Hello, 42
8



The virtual diamond:
Code:
#include <iostream>

struct A
{
    int x;
    A( int y ) : x(y) {
        std::cout << "A::A(" << y << ")\n";
    }
};

struct B1 : virtual public A
{
    B1() : A(7) {
        std::cout << "B1::B1()\n";
    }
};

struct B2 : virtual public A
{
    B2() : A(42) {
        std::cout << "B2::B2()\n";
    }
};

struct C : public B1, public B2
{
    C() : A(5), B1(), B2() // virtual base must be constructed here
    {
        std::cout << "C::C()\n";
    }
};

int main()
{
    C foo;
    std::cout << "Hello, " << foo.x << '\n';
    std::cout << "Hello, " << foo.B1::x << '\n';
    std::cout << "Hello, " << foo.B2::x << '\n';
    std::cout << sizeof(foo) << '\n';
    return 0;
}
Output:
A::A(5)
B1::B1()
B2::B2()
C::C()
Hello, 5
Hello, 5
Hello, 5
24

 
Stumbled upon these doing a review of new hire questions from (2000) and am stumped; never worried about these situations.
Are they real world or just hypothetical - my C++ training is not academic?

It's completely academic. In the real world, where you're writing code with the focus being on solving a problem, you just slop a bunch of code together. It usually starts with a jumble of global variables and a mishmash of classes and structs. It is only later, after you have something that works, that you put it into a somewhat proper form. Every piece of code I've ever looked at has always had questionable choices as to what is made public and what is kept private. And I never see friend classes at all.
 
It's completely academic. In the real world, where you're writing code with the focus being on solving a problem, you just slop a bunch of code together. It usually starts with a jumble of global variables and a mishmash of classes and structs. It is only later, after you have something that works, that you put it into a somewhat proper form. Every piece of code I've ever looked at has always had questionable choices as to what is made public and what is kept private. And I never see friend classes at all.

This is what I have seen and feel.
 
Back
Top