C++ base member access control

Started by
7 comments, last by the_edd 14 years ago
Just curious as to why this doesn't compile (Visual Studio 2008):

struct Base {
	void func(int n) {}
};

struct Derived : Base {
public:

	template<class T>
	void func(T const& p) {
		Base::func(20);
	}

private:
	using Base::func;

};

int main(int, char*[]) {
	Derived d;

	float f(5.f);

	d.func(f);
}

// Build log:
1>------ Build started: Project: testing, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>z:\my c++ projects\testing\testing\main.cpp(616) : warning C4100: 'n' : unreferenced formal parameter
1>z:\my c++ projects\testing\testing\main.cpp(637) : error C2248: 'Derived::func' : cannot access private member declared in class 'Derived'
1>        z:\my c++ projects\testing\testing\main.cpp(628) : see declaration of 'Derived::func'
1>        z:\my c++ projects\testing\testing\main.cpp(619) : see declaration of 'Derived'
1>Build log was saved at "file://z:\My C++ Projects\testing\testing\Debug\BuildLog.htm"
1>testing - 1 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

If I shift the derived function declaration below the using Base::func; it works ok. Is this a compiler bug?
Advertisement
Base::func needs to be virtual. Other than that, the code's ok.
Well, this is a simplified example, but I don't actually want it to be virtual... I understand that the base version will be hidden by the derived version, but shouldn't this still work?

GCC (well MinGW - not sure what version I have installed) compiles it ok.
The using shouldn't be private, it should be public.
That's also what the compiler is saying.
Someone who uses a, euhm..., delta!?
Quote:Original post by _fastcall
Base::func needs to be virtual. Other than that, the code's ok.


I don't think this has anything to do with virtual functions. It's about overload resolution.

Quote:Original post by delta user
The using shouldn't be private, it should be public.
That's also what the compiler is saying.

It's absolutely legal for to have private using declarations. There's nothing wrong with that.

The problem appears to be that VC++ is looking at both func methods in order to do overload resolution. As one of them is private, there's an access violation and compilation fails. I *think* this is correct. I'll try to find a reference.

Quote:Original post by sprite_hound
If I shift the derived function declaration below the using Base::func; it works ok. Is this a compiler bug?


There's probably a bug in g++ and/or VC++ but I wouldn't like to say which :)

EDIT: To clarify, I would expect that a conforming compiler would fail to compile the code regardless of the order in which the using directive and the func template are placed with respect to one another (as long as one of them is private in Derived).

EDIT 2: based on this article I have revised my opinion. Overload resolution occurs before access control. The best match for d.func(0.5f) is the templated member function. It's public so that should be allowed.

So I think g++ is correct and VC++ is wrong. Indeed, if you call d.func(1) instead, g++ fails to compile which is at least consistent with this logic.

[Edited by - the_edd on May 12, 2010 5:01:48 PM]
I must agree with a private using being valid, but i believe it wasn't meant to be private in this case.

It is annoying that VS is giving an error because it might be your intention to make it private.

On g++ on the other hand, the code compiles fine and runs the template function instead of the base function, which might not be what you intended.
Someone who uses a, euhm..., delta!?
Yeah, I want the base function to be private, and the template derived function to be public. VC++ seems to make both versions private with the using directive first.

the_edd, thanks for the article I didn't realise access control was considered afterwards.
I understand the problem with Visual Studio, but I'm wondering why use that method rather than this one?

struct Base {protected:	void func(int n) {}};struct Derived : Base {public:	template<class T>	void func(T const& p) {		Base::func(20);	}};


Making the base class's function protected seems to give you everything your looking for.
Adamhttp://www.allgamedevelopment.com
Quote:Original post by adam23
I understand the problem with Visual Studio, but I'm wondering why use that method rather than this one?

*** Source Snippet Removed ***

Making the base class's function protected seems to give you everything your looking for.


I don't think sprite_hound has actually said what they're looking for :) I'm guessing by the nondescript names in the code ("Base", "Derived", "func") that the example has been simmered down from real-world code to illustrate the problem.

But I'll bite; what advantage does your code provide? There's still the same snag with access violation.

This topic is closed to new replies.

Advertisement