Odd usage of friend keyword in C++ class.

Started by
7 comments, last by serratemplar 11 years, 1 month ago

It's my esteemed privilege to try and repair some old legacy code (or at least gather enough evidence to convince the powers at be to let my team rewrite it)...in digging through this code (which is devoid of comments) I've come across something that seems a bit weird. Here's a paraphrasing of the declaration:

[source]

class foo

{

public:

class event;

private:

class request

{

friend class event;

public:

doStuff();

private:

LOTS OF INTERNAL METHODS

}

class response

{

friend class event;

public:

doStuff();

private:

LOTS OF INTERNAL METHODS

}

}

[/source]

Now, I've seen nested class definitions before, and I've seen the friend keyword in use before, but I've never seen the friend keyword used like this. There are several other classes with this very structure, unspecified class 'event' friended to 'response' and 'request' and others. Is the goal to instantiate foo1, foo2, etc. then iterate over unspecified object pointers, controlling them through this 'event interface'?

Maybe it's a design paradigm one of you has seen in the past (and not just something this programmer made up) so I thought I'd ask. What could be gained from this? (Other than some obfuscation, which isn't out of the question.) Naturally it's hard (maybe impossible) to determine what the point is without the code base (which I can't share directly). However, these classes aren't instantiated in the code I have because it's a library, and while I technically know what the library accomplishes, I'm now at a loss as to how I might wield it.

Oh, I found a comment. It says "// TODO: FIX". It's the only one. I lol'd.

So, possibly you've seen this or have a sharper imagination than I. In any case, thanks in advance for your time. :)

Advertisement
Well in this case, there's a tight association between the request, response, and friend class, so the friend keyword allows the use of private variables and methods by the friend's methods. The friend keyword has nothing to do with the nested classes formally. However being nested members, and therefore part of the implementation of foo, may justify the break of encapsulation of individual nested classes. The "LOTS OF INTERNAL METHODS" suggests that foo may have too much responsibility, however.
Are there any other references to Foo::Event anywhere, or does it not exist?

Are there any other references to Foo::Event anywhere, or does it not exist?

The disappointing answer to this is, no. I'm grepping for instances of 'Event' over the tree and it's just not there. It's a library with no clear way to use it. (I am in the purely political process right now of getting my hands on a functional example.) The classes are never instantiated.

If nothing else, when I do get an example instantiation and usage, I'll share it here. (Assuming I don't convince people to let us replace it.)

This could have been added before Event was added, then Event never got used. There's nothing here that would prevent compilation without Event being defined somewhere. All it pre-declares is that there may be a class called Foo::Event that can access the private variables of Request and Response. If this then hasn't been implemented later on, it won't make any difference to anything.

This could have been added before Event was added, then Event never got used. There's nothing here that would prevent compilation without Event being defined somewhere. All it pre-declares is that there may be a class called Foo::Event that can access the private variables of Request and Response. If this then hasn't been implemented later on, it won't make any difference to anything.

Commenting out both "friend class event;" and doing a complete rebuild would fail to compile if Event actually is being used and is accessing private member variables, and the compiler will and tell you what file and linenumber event is being used to access the private member variables. You could do that to track down where Event actually is.

In the interest of a direct answer: that's a forward declaration wrapped in a friend clause.


class Foo {
    friend Event;
};

class Event {};

Compiler error - error C2433: 'Event' : 'friend' not permitted on data declarations


class Foo {
    friend class Event;
};

class Event {};

No problem! Equivalent to:


class Event;

class Foo {
    friend Event;
};

class Event {};

Apologies if this was obvious. If your question has to do with why it's being used like that, I haven't the faintest idea. It appears event, request and response are tightly coupled for some reason

I would expect different translation units to implement 'class event' differently.

It's a zero-overhead hook.

This is the kind of code you get when someone gives the green light to C++ but then says but no virtual functions!!!

Is there a chance that foo is a template class?

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

Is there a chance that foo is a template class?

Honestly, I don't believe so; nothing inherits from it and it's rather thoroughly flushed out.

The notion of it being an obscure style of forward declaration kind of blew my mind and depressed me at the same time.

I asked people local to me and the answers were a bit more jaded, haha. "That's what you get when you tell somebody to 'Do it in C++' and they don't know C++." Anyway, I've been retasked, so. dry.png Thanks everybody; sorry to leave this thread in such an unsatisfying state, but in a way I'm glad to be done with it. The issue presented here was only scratching the surface on funky stuff within.

Cheers.

This topic is closed to new replies.

Advertisement