Click here to Skip to main content
15,891,473 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I noticed that in Visual Studio 2013 that when one creates a new class, it assigns a file per class. I am accustomed to programming in C++ where I would put the main class with some helper classes.

I am putting together some basic demonstration code, and I want to avoid risky practices like dynamic memory allocation with the possibility of leaks from a missing Delete from New issue. So I was thinking of only keeping the dynamic memory allocation within the class constructor or destructor. Thus I would have a number of helper classes for different sorts of objects needed by the main class, in the same file as the main class. When I wrote C++ previously, I could keep these helper classes in the same file, but under Visual Studio I am getting the error message that these classes are not recognized!

I am leaning towards the approach of creating a static library project. But it seems like a bit of an over-kill. The idea of the .cpp file was to be a logical unit of code in one place before.

What is the common way of accomplishing this? I could use vector allocation, but I want a clean way of passing the information back and forth. I was looking as a in-between of creating a memory allocation and de-allocation class for each of the types of objects that need memory allocation. Before I would just keep the memory allocation in the cpp file?

1) Is there an option in Visual Studio 2013 to allow multiple classes in the same cpp file?
2) For the workaround memory class file creation, if one creates two types both based on integer, say "typedef int Type1; and typedef int Type2;" is this sufficient to create two constructors that override based on the type? I want to be able to create units of different kinds with the same initialization.
3) Right now I am trying the workaround of creating separate structures for each data type.

Any suggestions would be appreciated. Thank you!

Updated information in response to Solution #1:

I have a class file CDCDirectControls that has the class that I am writing.

From CDCDirectControls.h, the class for the file name and nested class is declared but not defined (using the guideline that in the header file declares and the .cpp file is used to define) :

Nested class definition - the class is nested to "cleanly" override the constructors, to provide the facility for different controls:

C++
class CCDCDirectControls : private CView
{
public:
	CCDCDirectControls();
	~CCDCDirectControls();
	class Button;
	CCDCDirectControls(CCDCDirectControls_Button x1);
}



Now in the CCDCDirectControls.cpp file, first is defined the nested class. Only after the nested class is defined, then is the constructor defined that is based on the nested class. Visual Studio 2013 seems to complain if the object is instantiated before it is defined with an error message.

C++
// Define object of type Button
class CCDCDirectControls::Button {   // Declare Button class type
public:
	int x_anchor;   // Declare member types
	int y_anchor;
};

//Now define the constructor override that uses the nested class button
CCDCDirectControls::CCDCDirectControls(CCDCDirectControls::Button x1)  //Constructor does nothing for now 
{
}


Finally, the call to the constructor was made like:
C++
CCDCDirectControls cdc1;
CCDCDirectControls cdc(CCDCDirectControls::Button x1);


I am going to work with this for a while and see how it goes. This seems like the cleanest approach to do this sort of thing. The Button nested-class can be used to define what it is. And then the constructor can be used to add the button on to the window. I was also able to compile with CCDCDirectControls as a static class also, but I had to make sure that the static class was of global scope (it seems a shame to just have to copy and comment the code inside the procedure itself).

Is there any cleaner way of doing this?


I found a reference to nested classes here:
nested classes - cppreference.com[1]

I found a reference to implementation of nested classes here:
Nested class' function: implementation c - C++ Forum[2]

I found a reference to the C2267 compiler error (when a static class is defined without global scope here)

Compiler Error C2267[3]

I worked around it using anonymous name space as here (and it compiled without error):

C++
// anonymous namespace to keep accidental override from occuring
namespace
{
	static CCDCDirectControls cdc3(CCDCDirectControls::Button x1);
}


A reference to usage of the anonymous name space is here: it is supposed to keep the static variable from being referenced outside of the .cpp file:

C++ initialize static variables in class? - Stack Overflow[4]

Updated:

In response to Solution #2 (and I appreciated the feedback), I looked up "std::unique_ptr"; now I have a bunch of code that references an existing array. The problem I might have with std::unique_ptr is the reference to it, but that seems covered by reference 5. It seems that unique_ptr might be the best way to dynamically allocate the memory. Both the new and delete operators can be used. But if something is forgotten or maybe the debugger exits early, it should in principle release everything fine. If there is a bug around it, good luck finding it! Thank you for the suggestion.

Reference to "std::unique_ptr" is here:

std::unique_ptr - cppreference.com[4]

std::unique_ptr::operator[] - cppreference.com[5]

How to reference the unique_ptr is here:

std::unique_ptr::get - cppreference.com[6]

Reference to delete and new still being used is here:

std::unique_ptr::release - cppreference.com[7]

I had noticed that in a nested class, that I was unable to instantiate a variable of the new class type. The solution is to make sure that the constructor is defined first, or else the compiler has no reference on how to instantiate the variable when it comes to it. It turns out that the issue is covered here:

C#
class CCDCDirectControls : private CView
{
public:
	CCDCDirectControls();
	~CCDCDirectControls();
	class Button      //Nested button class used to implement button
	{
	public:
		Button();
		~Button();
	};
	Button b1;
}


When building this up, it may not be necessary to make a constructor for every nested class from this reference:

c++ - In which cases there is no constructor at all, even a default constructor? - Stack Overflow[8]

There is still a question of why one would use the nested class to begin with. A brief explanation of the "why" behind it is here:

Inner class - Wikipedia, the free encyclopedia[9]

A nice reference to nested class scope is here:

C++ Annotations Version 10.5.0[10]
Posted
Updated 21-Jan-16 1:13am
v7

Quote:
When I wrote C++ previously, I could keep these helper classes in the same file, but under Visual Studio I am getting the error message that these classes are not recognized!
This behaviour would be wrong. You should be able to put many different classes in the same file. I just checked using VS2013 and it allows me to put (at least) two classes in the same source file.
 
Share this answer
 
Comments
StephenJElliott 19-Jan-16 4:30am    
I was getting an error message if the classes were declared below the referencing class... today I have an example with them declared above, and that almost works. I am trying to use a nested class now within the main class and then override the constructor ... I am trying to add more detail to the question now....
CPallini 19-Jan-16 4:58am    
Well, that's another matter, solved by class forward declaration
https://en.wikipedia.org/wiki/Forward_declaration
StephenJElliott 19-Jan-16 6:17am    
To quote from there, " C++ generally prohibits forward references, but they are allowed in the special case of class members." For me, that means if I am getting an error that might be a forward reference issue, check that out and proceed from there.
It's a bit hard working out what you're trying to do from the limited description in your question. A small example of what wasn't compiling would have been nice. Having said that...

Generally you want one interface [1] per include file and that include file should contain everything a client needs to know about the class. You then pile the implementation into another file.

Having said that there's no reason you can't pile the interfaces and implementations of multiple classes into the same file. You can even mix interface and implementation of these classes in the same file. Sometimes this is a good idea (if you can't use class A without class B for example), sometimes this is a bad idea (MFC I'm looking at you...).

In your question you mention missing a delete... Why are you still using new and delete? With C++11 the need for delete was just about eradicated and with C++14 the need for new went the same way. std::unique_ptr is your friend IF (and this is a big if) you actually need something that's dynamically allocated. Most of the time you don't.

[1] By interface I mean the class's defining declaration if you're into standard language.

[EDIT: Based on revised question...]

I wouldn't worry about using nested classes for the sort of thing you're up to (if I've got the right end of the stick). If all Button does is describe an origin for where you want a button displayed then just use a CPoint from MFC:

C++
class ControlView : public CView
{
    public:
        // Implementation in class definition 'cause I'm lazy - stick it in it's own file normally
        ControlView( const CPoint &anchor ) : anchor_( anchor )
        {
        }

    private:
        CPoint anchor_;
};


and leave the interface like that.

There's a couple of other things to note:

- using MFC it's very hard to control when a CView gets constructed during document creation and pass the constructor parameters. It might be better to just use a CWnd as your base class as there's less baggage to cart around and you can create one in a more or less arbitrary fashion. If CView's what you need for another reason then just ignore this!

- private inheritance of CView is not what you want. CView is designed to be publicly inherited from and private inheritance generally is another way of saying "uses" not "is kind of" the way public inheritance does.

Finally if you have a unique_ptr to something and want a reference to the underlying object then you can get one by dereferencing the unique_ptr:

C++
auto pa = std::make_unique<A>();
auto ref_a = *pa;


A quick look using intellisense will find that ref_a has a type A &.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900