• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lucky6969b

Compiler says class has no constructor while it actually has one

20 posts in this topic

activity = new Idle(this, NULL);

 

class Idle : public Activity

{

private:

    float mTimeInIdle;



public:

    Idle() : mTimeInIdle(0)    { }

    Idle(Objects *actor, Goods *target) : Activity(actor, target)

    {



    }

Error    1    error C2514: 'Idle' : class has no constructors    d:\jacky\documents\visual studio 2010\projects\perfectsim\perfectsim\perfectsim\Objects\Objects.h    43    1    PerfectSim
 

The activity = new Idle(this, NULL) line is located inside the Objects::Objects(...)  constructor.

Would it be caused by some cyclic dependencies? How do I go about resolving it?

Thanks

Jack

0

Share this post


Link to post
Share on other sites

I put everything inside header files. like Objects.h and Idle.h

 

#pragma once

#include "..\SkinnedMesh\skinnedMesh.h"
#include "..\Activities\Activity.h"
#include "DetourNavMeshQuery.h"
#include "MotiveBase.h"

//#include "..\myDX9Widget.h"

class myDX9Widget;
class Idle;

class Objects
{
public:
    Objects() : m_pAnimCtrl(0), energy(0) { }

    Objects(SkinnedMesh* _mesh) : m_pAnimCtrl(0)
    {
        SetPos(D3DXVECTOR3(0,0,0));
        SetRot(D3DXVECTOR3(0,0,0));
        SetRotCenter(D3DXVECTOR3(0,0,0));
        SetScale(D3DXVECTOR3(1,1,1));
        SetScaleCenter(D3DXVECTOR3(1,1,1));

        D3DXQUATERNION quat;
        D3DXQuaternionIdentity(&quat);

        SetRotQuat(quat);
        
        
        if (_mesh->GetMasterAnimCtrl() != NULL)
        {
            _mesh->GetMasterAnimCtrl()->CloneAnimationController(
            _mesh->GetMasterAnimCtrl()->GetMaxNumAnimationOutputs(),
            _mesh->GetMasterAnimCtrl()->GetMaxNumAnimationSets(),
            _mesh->GetMasterAnimCtrl()->GetMaxNumTracks(),
            _mesh->GetMasterAnimCtrl()->GetMaxNumEvents(),
            &m_pAnimCtrl);
        }
        

        activity = new Idle(this, NULL);
        
        mesh = _mesh;
    }
Edited by lucky6969b
0

Share this post


Link to post
Share on other sites

Now that I've included Idle.h in Objects.h

so that Objects should see everything in idle, that's point 1

Point 2, idle can't see everything in Objects. So I forward declare it, otherwise, I have a circular references, Objects->Idle and Idle->Objects

 

How do I make Idle see Objects so I won't get the following errors:

Error    1    error C2027: use of undefined type 'Objects'    d:\jacky\documents\visual studio 2010\projects\perfectsim\perfectsim\perfectsim\Activities\Idle.h    29    1    PerfectSim
Error    3    error C2027: use of undefined type 'Objects'    d:\jacky\documents\visual studio 2010\projects\perfectsim\perfectsim\perfectsim\Activities\Idle.h    33    1    PerfectSim
Error    10    error C2027: use of undefined type 'Objects'    d:\jacky\documents\visual studio 2010\projects\perfectsim\perfectsim\perfectsim\activities\Idle.h    29    1    PerfectSim
 

0

Share this post


Link to post
Share on other sites

You can break the circular dependency if you split your implementation and declaration into .cpp and .h-files

 

Only declare the classes in the header-files, no method implementations.

You can have only a forward declaration in the .h-file if you only have pointers to the classes in the .h-file

 

Then include the full header in the cpp-file to be able to call its methods.

1

Share this post


Link to post
Share on other sites

I put everything inside header files.

That simply will not work in C++ in general. Any code in Objects.h that needs to see more than the forward declaration should be moved into an implementation file which can see the whole interface of Idle.

There are languages which do not require (or even allow) the separation between header and implementation that C++ usually requires, but I would suggest switching languages if you really want it that badly. Trying to force it on C++ will just lead to pain and suffering.
2

Share this post


Link to post
Share on other sites

Please do a quick check on my coding

Activity.h

#include <string>
 

class Idle;
class Objects;
class Goods;

class Activity
{
public:
    Objects *Actor;
    Goods *Target;
    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }

    virtual bool OnUpdate(float seconds) = 0;

    void Update(float seconds);
    

    Activity *FindBestActivity(Objects *actor);
    
    std::string ToString();

};

 

Idle.h

#include "Activity.h"
 
 
 

#define MAX_IDLE_TIME 8
#define ACTIVITY_IDLE_ENERGY 1.0

class Objects;
class Activity;

class Idle : public Activity
{
private:
    float mTimeInIdle;

public:
    Idle() : mTimeInIdle(0)    { }
    Idle(Objects *actor, Goods *target);

    bool OnUpdate(float seconds);
    

};

 

idle.cpp

#include "Idle.h"

 

Idle::Idle(Objects* actor, Goods *target) : Activity(actor, target)
{

}

bool Idle::OnUpdate(float seconds)
{

    mTimeInIdle += seconds;
    if (mTimeInIdle >= MAX_IDLE_TIME)
    {
        Actor->activity = FindBestActivity(Actor);
    }


    Actor->energy += ACTIVITY_IDLE_ENERGY * seconds;
    return false;
}

Error    1    error C2027: use of undefined type 'Objects'    D:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\PerfectSim\Activities\Idle.cpp    16    1    PerfectSim
Error    3    error C2027: use of undefined type 'Objects'    D:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\PerfectSim\Activities\Idle.cpp    20    1    PerfectSim
Error    2    error C2227: left of '->activity' must point to class/struct/union/generic type    D:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\PerfectSim\Activities\Idle.cpp    16    1    PerfectSim
Error    4    error C2227: left of '->energy' must point to class/struct/union/generic type    D:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\PerfectSim\Activities\Idle.cpp    20    1    PerfectSim
 

 

I've moved everything into implementation file. Here now are what I've got.

Thanks

0

Share this post


Link to post
Share on other sites

From quickly glancing over it the problem seems to be the obvious failure to include Activity.h in Idle.cpp. 

1

Share this post


Link to post
Share on other sites

From quickly glancing over it the problem seems to be the obvious failure to include Activity.h in Idle.cpp.

Idle.cpp includes Idle.h, which in turn includes Activity.h.

It seems that the problem is that you're dereferencing the Objects class in the Idle::OnUpdate() method, while you only have a forward declaration. You'll need to include the header for all objects that you will need more than a pointer or reference to in order to use them. If this causes a circular dependency or circular header-inclusion, then the hierarchy of files needs to be fixed. Edited by Ectara
1

Share this post


Link to post
Share on other sites
Not a bug, but what happened here?
    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }
1

Share this post


Link to post
Share on other sites

Not a bug, but what happened here?

    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }

Default constructor sets Actor and Target to NULL?

 

OP, you need to include objects.h and activity.h in idle.cpp

1

Share this post


Link to post
Share on other sites

 

Not a bug, but what happened here?

    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }

Default constructor sets Actor and Target to NULL?

 

OP, you need to include objects.h and activity.h in idle.cpp

 

Thank you for that... rolleyes.gif

 

There's two constructors there. I was asking why he uses initializers in one and manual assignments in the other.

1

Share this post


Link to post
Share on other sites

 

 

Not a bug, but what happened here?

    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }

Default constructor sets Actor and Target to NULL?

 

OP, you need to include objects.h and activity.h in idle.cpp

 

Thank you for that... rolleyes.gif

 

There's two constructors there. I was asking why he uses initializers in one and manual assignments in the other.

My guess is the assumption that only constants can be used in initializer lists.

1

Share this post


Link to post
Share on other sites

The hierarchy is as follows

 

Objects.h includes Idle.h

Idle.h includes activity.h

 

The problem I am having is Objects would instance Idle, which derives from Activity

And Idle has a pointer referencing Objects as well in turn.

 

Would that be a problem if I instance Idle in the header file called Objects.h, not in the implementation file as well

Thanks

Jack

Edited by lucky6969b
0

Share this post


Link to post
Share on other sites

 

 

Not a bug, but what happened here?

    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }

Default constructor sets Actor and Target to NULL?

 

OP, you need to include objects.h and activity.h in idle.cpp

 

Thank you for that... rolleyes.gif

 

There's two constructors there. I was asking why he uses initializers in one and manual assignments in the other.

 

What is the general practice when confronting with this situation?

Thx

Jack

0

Share this post


Link to post
Share on other sites

What is the general practice when confronting with this situation?

 Activity( Objects* actor, Goods* target ) : Actor(actor), Target(target)
 {
 }
As for your compile errors:

It seems you have a misunderstanding about compilation units and forward-declaration in general here. From your errors, for example...
error C2027: use of undefined type 'Objects'    D:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\PerfectSim\Activities\Idle.cpp    16    1    PerfectSim
...the Idle.cpp compilation unit has no idea what the Objects class looks like; which is, of course, because Idle.cpp only #includes Idle.h. Idle.h only #includes Activity.h. Neither of these include Objects.h, so the compiler has no way of knowing what Objects looks like, what members or methods are accessible, or even that it exists as a class.

Forward declaration is used to inform the compiler that there is a class called Object, but it still doesn't give the compiler any indication of what that class looks like. It is sufficient to forward declare a class in a header if, for example, you use a pointer to that class somewhere in another class definition; but if you actually want to call any methods or reference any members of that class, then a forward declaration isn't sufficient and the compiler will, at that point, need the full class declaration from the class header to be included.

Now, you say that Object.h includes Idle.h, which includes Activity.h, so including Object.h into the Idle.cpp compilation unit would cause a problem, since Idle.h is already explicitly included, resulting in a multiple declaration. Removing the include of Idle.h and just including Object.h instead would solve it, but problems of multiple definition like this are why people commonly use what are called include guards, either the pre-processor directive #pragma once or an #ifndef structure like this:
#ifndef IDLE_H
#define IDLE_H
// Class declaration here
#endif
Using pre-processor directives like this means that you can safely include a header multiple times in a compilation unit, but it will only actually be included once. If Activity.h, Idle.h and Object.h were all properly equipped with include guards, then you can safely include them wherever needed, without worrying about redeclaration errors.

Watch out for circular dependencies. If you have something like this:
// Foo.h
#ifndef FOO_H
#define FOO_H
#include "Bar.h"

class Foo
{
  public:
  Bar bar_;
};
#endif
// Bar.h
#ifndef BAR_H
#define BAR_H
#include "Foo.h"

class Bar
{
  public:
  Foo foo_;
};
#endif
then you have a problem. This sort of code structure is not allowed. If you study the nesting you should see why. Foo contains an instance of Bar, which contains an instance of Foo, which contains an instance of Bar, and so on until out-of-memory exception, infinity, or the heat-death of the universe, whichever comes first. It is, however, legal to achieve the same with pointers, as you seem to be doing despite your statements that Objects.h instanced Idle:
// Foo.h
#ifndef FOO_H
#define FOO_H

#include "Bar.h"

class Foo
{
  public:
  Bar *bar_;
};

#endif
//Bar.h
#ifndef BAR_H
#define BAR_H

#include "Foo.h"

class Bar
{
  public:
  Foo *foo_;
};
#endif
Doing it this way is okay. Note that if you didn't have include guards, though, it would fail because including Foo.h would also include Bar.h which would in turn include Foo.h, which would again include Bar.h, and so on, yada yada yada, heat death. But the include guards mean that once the set of declarations enclosed by the guards have been processed, they won't be processed again, so including Foo.h will include Bar.h, which will try to include Foo.h but since it has already been included it amounts to a no-op and Bar.h will not be included again.

This, however, is not really recommended. If the class Foo is only ever referred to in pointer definitions in Bar.h, and Bar is only ever referred to in pointer definitions in Foo.h, then there is no need for either header to explicitly include the other. This is where forward declarations come in:
// Foo.h
#ifndef FOO_H
#define FOO_H

class Bar;
class Foo
{
  public:
  Bar *bar_;
};
#endif
// Bar.h
#ifndef BAR_H
#define BAR_H

class Foo;
class Bar
{
  public:
  Foo *foo_;
};
#endif
If nothing inside the Foo.h header needs to know what Bar looks like (ie, what methods or members it has) but just has to be able to deal with a pointer to Bar, then it is preferred to merely forward declare Bar rather than explicitly include Bar.h. This removes a compile-time dependency between the two modules. If the two headers explicitly include each other, and a change is made to one header, then any compilation unit where either of those headers is included will end up being re-compiled even if it wouldn't normally be necessary. By removing the explicit inclusion and using forward declaration instead, you can skip some needless recompiling. Note, however, that if the Foo.cpp compilation unit makes any kind of use of the Bar pointer member (ie, using it to call any Bar methods or access any Bar members) then Foo.cpp will need to include Bar.h so that the compiler knows what it looks like. Similarly with Bar.cpp including Foo.h.

Forward declaration is also useful for setting up circular pointer-based dependencies that occur within the same header:
// FooBar.h
#ifndef FOOBAR_H
#define FOOBAR_H

class Bar;
class Foo
{
  public:
  Bar *bar_;
};

class Bar
{
  public:
  Foo *foo_;
};

In this example, when Foo is declared, Bar hasn't yet been declared so the only way Foo has of knowing that Bar is even a class type is through the forward declaration of Bar.

Now, say you want to change the pointer to Bar that Foo holds into an actual instance of Bar:
// FooBar.h
#ifndef FOOBAR_H
#define FOOBAR_H

class Bar;
class Foo
{
  public:
  Bar bar_;
};

class Bar
{
  public:
  Foo *foo_;
};

#endif
This won't work, because since Foo is dealing with an instance of Bar rather than just a pointer to it, forward declaration is no longer sufficient. The compiler needs to know what Bar looks like, in order to know how big a piece of memory to allocate for it inside the Foo memory structure. Similarly, if any inlined functions declared in the class declaration of Foo call bar_'s methods, then forward declaration is no longer sufficient. This won't work:
// FooBar.h
#ifndef FOOBAR_H
#define FOOBAR_H

class Bar;
class Foo
{
  public:
  Bar *_;

  inline void baz()
  {
    if(bar_) bar_->qux();
  }
};

class Bar
{
  public:
  Foo *foo_;

  void qux();
};
#endif
At the point of defining the method Foo::baz, the inline function definition explicitly calls the method Bar::qux, meaning that at that point the compiler will need to know what Bar looks like, and the forward declaration isn't sufficient. In this case you'll probably want to forego defining any methods, inline or otherwise, inside the header file and put them in the compilation unit instead. Granted, reversing the order that Foo and Bar appear, and forward declaring Foo for Bar's declaration, would solve the issue but it wouldn't solve the problem presented here:
// FooBar.h
#ifndef FOOBAR_H
#define FOOBAR_H

class Bar;
class Foo
{
  public:
  Bar * bar_;

  inline void baz()
  {
    if(bar_) bar_->qux();
  }
};

class Bar
{
  public:
  Foo *foo_;

  inline void qux()
  {
    if(foo_) foo_->baz();
  }
};
#endif
... which, ignoring for a moment the infinite recursion loop, simply wouldn't compile given the insufficiency of the forward declaration.

So just remember: use forward declaration if you only need to know if a class exists but don't care what it looks like, but explicitly include the class header file if you need to know what it looks like. Use include guards to prevent multiple declarations of classes. And sorry for the long post; it kind of got away from me. Edited by JTippetts
2

Share this post


Link to post
Share on other sites




Not a bug, but what happened here?

    Activity() : Actor(0), Target(0) { }
    Activity( Objects* actor, Goods* target )
    {
        Actor = actor;
        Target = target;
    }
Default constructor sets Actor and Target to NULL?

OP, you need to include objects.h and activity.h in idle.cpp

Thank you for that... rolleyes.gif

There's two constructors there. I was asking why he uses initializers in one and manual assignments in the other.

What is the general practice when confronting with this situation?
Thx
Jack
Always use the initializer list, unless you have a specific reason NOT to. The quoted code above does not have any reason not to use it so both constructors should use the initializer list.
1

Share this post


Link to post
Share on other sites

One error left.

 

activity = new Idle(this, NULL);

 

Error    1    error C2514: 'Idle' : class has no constructors    d:\jacky\documents\visual studio 2010\projects\perfectsim\perfectsim\perfectsim\Objects\Objects.h    44    1    PerfectSim
 

The strange thing was I already had my constructor set in place.

 

#pragma once

#include "Activity.h"
#include "..\Objects\Objects.h"
 
 
 
 

#define MAX_IDLE_TIME 8
#define ACTIVITY_IDLE_ENERGY 1.0

class Objects;
class Activity;

class Idle : public Activity
{
private:
    float mTimeInIdle;

public:
    Idle() : mTimeInIdle(0)    { }
    Idle(Objects *actor, Goods *target) : Activity(actor, target) { }

    bool OnUpdate(float seconds);
    

};

The previous errors have been fixed after adding the pragma directive.

Thank the guys who helped.

Jack

Edited by lucky6969b
0

Share this post


Link to post
Share on other sites
If the line activity = new Idle(this, NULL); occurs inside Objects.h, as seems to be indicated by the info in the error message, then it's probably because where that line occurs there has only been a forward declaration of Idle. Go read what JTippetts posted again. If you want to use anything that is part of the class Idle (including constructors) then before you do so you have to include the full declaration of Idle. If the compiler encounters new Idle, and it still doesn't know what the fuck Idle looks like because all it has to work from is a forward declaration, then you're going to get that error. Whenever you have cyclical-dependency fuckery, you would probably be better off not putting any executable code at all inside your headers and keep it all to .cpp files.
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0