Q:

class prototype creation c++

#include <iostream>    
using namespace std;

class Rectangle;

int main () {
    Rectangle rect (3,4);
    Rectangle rectb (5,6);
    cout << "rect area: " << rect.area() << endl;
    cout << "rectb area: " << rectb.area() << endl;
    return 0;
}

class Rectangle {
    int width, height;
public:
    Rectangle (int,int);
    int area () {return (width*height);}
};

Rectangle::Rectangle (int a, int b) {
    width = a;
    height = b;
}

I do know that there are tons of posts like this, however none of them have seemed to fix my error called Variable has incomplete type (class_name_here).
All I want to be able to do is, to create the class after the main block and still fully use it by creating a "prototype" before the main block. I thought: well, that's simple, but just couldn't fix it.

A:

Forward declarations of a type create a so-called incomplete type -- a type that is known to exist, but the characteristics of which are not yet known.
You cannot declare variables of an incomplete type.  This is because the compiler needs to know how much space to allocate for the Rectangle objects as well as what constructors exist for that type.  Note that you couldn't call area() on the objects either since the compiler has not seen a declaration of that method yet.
You can declare variables that point to or are references of an incomplete type, but you can't actually do anything with them except simple assignment of the pointer or reference or passing them to other functions that accept pointers/references until the type is complete.
class Rectangle;

Rectangle & get_rectangle();

int main(void) {
    // OK, this is a reference.
    Rectangle & r = get_rectangle();

    // OK, this is a pointer.
    Rectangle * rp = &r;

    // Not OK; the compiler doesn't know (a) how much space to allocate on the stack,
    // nor (b) if the type has a default constructor.
    Rectangle rect;

    // Not OK; the compiler has not seen a declaration of Rectangle so it doesn't know
    // whether the area() method exists, nor its signature.
    r.area();
    rp->area();

    return EXIT_SUCCESS;
}

Typically you use forward declaration of types when you have some circular dependency between types, for example some child node type that needs a reference to its parent, but the parent type contains children.
class Parent;

class Child {
private:
    Parent & parent;
};

class Parent {
private:
    std::vector<Child> children;
};

This technique is also used by the opaque pointer idiom or pimpl pattern, where you store all data members in your class inside of another object whose type is not exposed to code that consumes it.  This allows you to change the data members without breaking the binary interface of your code.  (Normally adding or removing or changing a data member would cause the size and/or layout of objects of the class to change, for example. This approach causes the size to remain constant; you simply store a pointer to the data, and the data class can change layout without your consumers having to know or care.)
class Something {
private:
    class Data;
    std::unique_ptr<Data> data;
};

Code that uses your library has no idea what Something::Data is but it doesn't have to care.  Then in your implementation file for Something you define this class.
In your case, there is no reason to use forward declaration.  Just replace the forward declaration with the actual class definition.

