Visual Studio allows unrelated class method to access nested private class? - c++

I am trying to build my project on both linux and windows. The project is already working on windows but I am facing a very weird error on GCC. Consider the following code:
Class Base {
private:
MessageInfo *createMsg();
}
Class MessageInfo {
private:
class Message{
...
}
public:
Message *messages[MAX_NO_MESSAGES];
...
}
MessageInfo *Base::createMsg(){
...
MessageInfo *newMsg = new MessageInfo;
newMsg->messages[i] = new MessageInfo::Message();
...
}
Now the problem is that in Visual Studio every thing compiles but in GCC I get the following error:
*Error: Class MessageInfo::Message is private
I am really surprised that the code actually compiles in Visual Studio but not in GCC. Any Suggestions???
EDIT:
I think I have to ask my question in a better way. My question is how is that even possible to compile such code in VS 2005??? I tried my code in VS2013 and it gave me the same error as GCC. So I am not arguing that the code is correct!

This does not compile in Visual Studio 2013:
class MessageInfo {
class Message { };
public:
Message *messages[256];
};
class Base {
MessageInfo *createMsg();
};
MessageInfo *Base::createMsg() {
MessageInfo *newMsg = new MessageInfo;
newMsg->messages[0] = new MessageInfo::Message(); // won't compile
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
The error, as you would expect, is:
error C2248: 'MessageInfo::Message' : cannot access private class declared in class 'MessageInfo'

Compilers are so different and I'm not really sure why VS would allow that to compile, any compiler I've used would have thrown a compile error.
What you're doing though is a bad way to think of a class. If you have the
class Message {...};
private in MessageInfo, then you shouldn't be able to access it anywhere outside of the class. We would only want Message to be available inside of the MessageInfo class and nowhere else. So you shouldn't return a Message* as you do in MessageInfo and you won't be able to access the Message() constructor as you do in main. Programming this way isn't allowed because otherwise it would completely goes against the purpose of encapsulation. If you really do want Message to be available to anyone, then make it public, but usually the inner workings of a class are hidden away from the user good reason: they shouldn't need to worry about it.

As suggested by egrunin I used the code that he suggested in his comment. Apparently you cannot compile that code in Visual Studio 2013 but I successfully compiled it on my machine using Visual Studio 2005. Here is the complete code that
used:
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
class MessageInfo {
class Message { };
public:
Message *messages[256];
};
class Base {
MessageInfo *createMsg();
};
MessageInfo *Base::createMsg() {
MessageInfo *newMsg = new MessageInfo;
newMsg->messages[0] = new MessageInfo::Message(); // won't compile
return newMsg;
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Am I doing some thing wrong here???
P.S:
I tried the code on Visual Studio 2010 and I got the cannot access private class declared in class 'MessageInfo' error!! Can anyone compile this code on Visual Studio 2005 so that I know what is wrong with VS 2005????

Related

Error code = 0x80070002 (MS Visual Studio) C++

Well, I wrote a simple code to check the possibility of creating objects using 'new' operator. When I was trying to compile the code, the MS Visual Studio threw the error like this: " Error: Unable to open file C:\Users...\test1\Debug\main.obj. Error code = 0x80070002.Error: Could not find 'C:\Users...\test1\Debug\main.obj'. test1.exe was built with /DEBUG:FASTLINK which requires object files for debugging.
What is going on? Please help.
Code:
#include <iostream>
class czlowiek {
int wiek;
char plec;
czlowiek();
czlowiek(int Wiek, int Plec);
};
czlowiek::czlowiek(int Wiek, int Plec) {
wiek = Wiek;
plec = Plec;
}
int main()
{
czlowiek *first;
first = new czlowiek();
delete first;
std::cin.get();
return 0;
}
The code you posted will not link:
The constructor czlowiek() doesn't have an implementation.
Both constructors are private (in classes members and methods are private by default).
As warning, you are assigning a int to a char (plec).

VS 2015 Update 3 Internal compiler Error when curiously recursive template pattern with name hiding is used

Here is a small,standalone use case that I am trying to compile using VS2015 Update 3 compiler.
template <typename Derived, typename SomeType> class BaseClass
{
public:
void NameHidingMethod(SomeType const & node)
{
// Do Something
}
};
namespace structured {
typedef struct _Structure
{
} Structure;
template <typename Derived>
using BaseClass = BaseClass<Derived, Structure>;
}
class DerivedClass : public structured::BaseClass<DerivedClass>
{
public:
using structured::BaseClass<DerivedClass>::NameHidingMethod; // Generates error
};
int main() {
return 0;
}
This works fine on VS 2013 but fails VS 2015 Update 3. Here is the error message that I get.
fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\c\symbols.c', line 5786)
To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
Is my code legit ? If yes, then what could be a possible workaround ?

VS2013 is having trouble with base class being in unnamed namespace

The following code compiles fine and runs as expected:
#include <iostream>
namespace
{
struct Base
{
void print() const { std::cout << "test"; };
};
};
class Derived : public Base
{
};
int main()
{
Derived d;
d.print();
return 0;
}
But when looking at d during runtime using QuickWatch, IntelliSense seems to be unable to find
Base.
I solved this by putting Base in a named namespace instead of an unnamed.
So is it a bug in Visual Studio, or am I missing something out?
This problem with anonymous namepaces has been an issue in VC++ for a while - see http://msdn.microsoft.com/en-us/library/0888kc6a%28VS.80%29.aspx. From the linked doc:
The native C++ expression evaluator does not support anonymous namespaces.
and
The only way to watch the symbol test in this example is to use the decorated name:
e.g. (int*)?test#?A0xccd06570#mars##3HA (using the namespace hierarchy given in the example to illustrate the point). Just use the decorated name? That's so convenient! Thanks, Microsoft.

Effective C++ Item 43 Know how to access names in templatized base classes

In Item 43 of the book, it is said that the code below will not compile.
My understanding is that, compilation error occurs when the method LoggingMsgSender::sendClearMsg is instaniated.
However, for the three compilers (VC 2005, gcc 4.4.1, and one for embeded device) I have tried.
None of them show any compilation error.
Are there any compiler which can show the error as mentioned in the book?
Any suggestions are welcome.
Thank you for your help.
(I have found a potential compiler bug in VC 2005 in my source related to this kind
of template base-class function call, that's why I want to the compilation error.
That's a long story...)
class CompanyX
{
public:
void sendClearText(){};
};
typedef int MsgInfo;
template<typename Company>
class MsgSender {
public:
void sendClear(const MsgInfo&)
{
Company c;
c.sendClearText();
}
};
template<typename Company>
class LoggingMsgSender : public MsgSender<Company> {
public:
void sendClearMsg(const MsgInfo& info)
{
sendClear( info ); // ERROR : will not compile despite clearly being in base class.
}
};
int main()
{
LoggingMsgSender<CompanyX> sender;
sender.sendClearMsg(1); // specialization of the method!!!
}
http://liveworkspace.org/code/273c71cd53111dd8c6aaa54e64c53548 for example. get an error. in this case in function sendClearMsg we should use this->sendClear(info); compiler is gcc 4.7.1. And so, now is 2012 year, why you use old compilers?

calling std::cout.rdbuf() produces syntax error

Maybe I missed something, but I cant figure out why Visual Studio 2008 isn't seeing the rdbuf() procedure. Here is my code:
16. #include "DebugBuffer/BufferedStringBuf.h"
17.
18. BufferedStringBuf debug_buffer(256);
19. std::cout.rdbuf(&debug_buffer);
The BufferedStringBuf class is from this page: http://www.devmaster.net/forums/showthread.php?t=7037
Which produces the following error:
...src\main.cpp(19) : error C2143: syntax error : missing ';' before '.'
All I want to do is redirect std::cout to the Visual Studio Output window using OutputDebugString()..
You're not allowed to have executable statements at file-level scope. You can declare variables, but you can't call functions as standalone statements. Move your code into a function (such as gf's answer demonstrates), and you should have no problem.
Using the example class given on that site i don't have any problem:
#include <iostream>
#include "DebugBuffer/BufferedStringBuf.h"
class DbgBuf : public BufferedStringBuf {
public:
DbgBuf() : BufferedStringBuf(255) {}
virtual void writeString(const std::string &str) {}
};
int main()
{
DbgBuf debug_buffer;
std::cout.rdbuf(&debug_buffer);
}
Note that you have to create an instance of a class that derives from BufferedStringBuf because BufferedStringBuf::writeString() is pure virtual, thus making it an abstract class - abstract classes can't be instantiated.