class Building{
private:
int floor;
public:
Building(int s) { floor = s;}
};
int Main(){
Building twin, star;
Building BlueHouse(5), JangMi(14);
}
I made this code, and when I build the code 'error C2512: 'Building' : no appropriate default constructor available' comes up. It's been only a few weeks since I'v started learning c++ , and I'm having quite a hard time ;< Help me out, c++ masters!
When you write:
Building twin, star;
it means to create twin and star using the default constructor, since you didn't provide any initializers. But you have not defined a default constructor, so this is an error.
To fix this, add a default constructor, e.g. within class Building's public section:
Building(): floor(0) {}
Note that I used the syntax for initializing variables in the constructor, this is actually the same as Building() { floor = 0; } when floor is just an int, but if you had other member variables which were of class type, then there is a difference.
Alternatively you could add a default value to your existing constructor:
Building(int s = 0): floor(s) {}
Related
I have some code that I am using to convert arbitrary QObject subclasses to JSON. I able to convert them if they are pointers to a subclass, but am curious whether it is possible to convert instances (provided the subclass implements a copy constructor). Is there some crazy way to use something like templates or the type information provided by QMetaType to copy an instance of a QObject subclass without knowing what it is? The ToJson code is in a class that has no knowledge of the subclass.
I think it might be possible with QMetaType::create or something similar but I haven't been able to figure out how to actually copy the properties of the subclass instance.
Here's my code for converting:
QJsonValue ToJson(QVariant value){
switch(value.type()){
case QVariant::Int:
case QVariant::Double:
return value.toDouble();
////Other cases, etc...
case QVariant::UserType:
QObject* obj_ptr = qvariant_cast<QObject*>(value);
if(obj_ptr) // value was originally a pointer to a QObject, works correctly
return ToJson(obj_ptr);
else { // value was orginally an instance of a QObject subclass
std::string t = value.typeName(); //returns "MyQObject"
int id = QMetaType::type(t.c_str()); //returns the id of the derived class
void* v = QMetaType::create(id, &value); //passing &value does nothing
obj_ptr = static_cast<QObject*>(v);
return ToJson(obj_ptr); //works, but resulting fields are all default
}
}
}
QJsonObject ToJson(QObject* o){
QJsonObject obj;
auto mo = o->metaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
QVariant value = o->property(mo->property(i).name());
obj[mo->property(i).name()] = ToJson(value);
}
return obj;
}
Sample code use case:
qRegisterMetaType<MyQObject>();
MyQObject obj;
obj.db = 11.1;
QVariant test1 = QVariant::fromValue(obj);
QVariant test2 = QVariant::fromValue(&obj);
QJsonValue v1 = ToJson(test1); // default constructed values
QJsonValue v2 = ToJson(test2); // db = 11.1
Sample QObject subclass:
class MyQObject : public QObject {
Q_OBJECT
Q_PROPERTY(double DB MEMBER db)
Q_PROPERTY(int I MEMBER i)
public:
MyQObject();
MyQObject(const MyQObject& other) : QObject() {
i = other.i;
db = other.db;
}
int i = 50;
double db = 1.5;
};
Q_DECLARE_METATYPE(MyQObject)
Is there any way to handle the case illustrated by test1 above?
Long-story-short: nope. There is no way to store QObjects by value in containers or QVariant.
Qt forbids the copy of QObjects and all inheriting classes. The mandatory the Q_OBJECT macro will disable any copy constructor also in newly defined classes.
The copy constructor that you are defining in the MyObject class is missing the base class constructor call. If QObject had a copy constructor it would be something like this:
MyQObject(const MyQObject& other) :
QObject(other) // this will NEVER compile
{
i = other.i;
db = other.db;
}
Probably, the compiler is giving you a warning, but allows you to have such a constructor, even if it will result in undefined behavior or slicing an instance of MyObject every time it is passed by value.
Furthermore, the Qt docs states the following:
The values stored in the various containers can be of any assignable
data type. To qualify, a type must provide a default constructor, a
copy constructor, and an assignment operator. This covers most data
types you are likely to want to store in a container, including basic
types such as int and double, pointer types, and Qt data types such as
QString, QDate, and QTime, but it doesn't cover QObject or any QObject
subclass (QWidget, QDialog, QTimer, etc.).
So you can't store QObject and derived classes inside a Qt container unless you store them as pointers, as copy of QObjects is disabled by design.
Furthermore, if you want to exploit polymorphic behavior you must use pointers, even if there is no explicit need to cast to derived classes in your code, as far as I can see. If you really need to resort to casting in some place, you could consider making your ToJson a template function.
There is a solution, but use caution as it is only reasonable/applicable in the following scenario:
Classes in question are primarily data storage classes
The classes in question would be entirely copy-able if they didn't inherit from QObject
Most importantly, the ONLY reason you have the class inherit from QObject is so that it can have meta properties.
If your code uses the class as a QObject for any reason other than to get meta information, you are almost certainly using it incorrectly if you are trying to store it by value (as explained by G. Giordano in their answer).
Misuse considerations aside, in order to JSON-ify a QVariant that stores a QObject subclass by value, you can use the QMetaType::create method and pass it the user type id and yourQVariant.constData().
Example:
MyQObject obj;
obj.db = 11.1;
QVariant value = QVariant::fromValue(obj);
std::string t = value.typeName();
int id = QMetaType::type(t.c_str());
void* v = QMetaType::create(id, value.constData());
obj_ptr = static_cast<QObject*>(v);
QJsonValue json = ToJson(obj_ptr); //json contains db = 11.1
I have a XAML + DirectX app and I want to add static field to my "interop" class:
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Direct3DInterop sealed : public Windows::Phone::Input::Interop::IDrawingSurfaceManipulationHandler
{
public:
static int VALUE = 0;
...
};
It does not compile saying "only static const integral data members can be initialized within a class".
If I change it to const static int VALUE = 0; then it still does not compile with error "a non-value type cannot have any public data members"
What am I doing wrong?
WinRT public classes have a number of limitations to ensure they are consumable by multiple languages including C++, JavaScript, and C#. This is why you are getting error C3984. You can't have public fields and instead must use properties. You'd make it a read-only property:
property int VALUE
{
int get() { return 0; }
}
It is important to remember that properties are function calls and can't usually be optimized away, so you should consider that when designing the interfaces.
If you intend to have this class only consumable by C++, consider not using a WinRT class and instead use a simple C++ class which you managed the lifetime using std::unique_ptr or std::shared_ptr. In that case, you can of course use the public field approach as always.
The original problem you got is a general C++ language restriction not specific to WinRT. Error C2864 (you are using VS 2012 from the text you posted) is a little more general with C++11 in VS2013.
I am trying to develop a method in actionscript that takes a Class object as a parameter and will generate an instance of that class at runtime:
public function getComponent(componentType:Class):Object
{
return new componentType();
}
In some cases I may be passed a Class object that represents an interface instead. Naturally I cannot directly create an instance of an interface.
Is there some way to query the Class object and determine whether or not it represents an interface so that I can avoid trying to create an instance in this way?
Assume you follow a naming convention for your interface class, as in the standard IInterfaceName, name of the interface prefixed with a capital "I" following a capital letter and the rest of the class name. There are a couple of ways to do this. If you have a lot of different interfaces that could be passed as a parameter you could do this:
First import the flash.utils.getQualifiedClassName and in your function:
public function getComponent(componentType:Class):Object
{
var name:String = getQualifiedClassName( componentType ).replace(/.*\:+/g,"");
if ( name.search( /^\I[A-Z]/g ) != -1 ) {
trace( "parameter is an interface!" );
return null;
}
return new componentType();
}
You don't have to set the name variable, but this helps make the search a little more strict. You could just do this instead:
if ( getQualifiedClassName( componentType ).search( /\I[A-Z]/g ) != -1 ) {
trace( "parameter is an interface!" );
return null;
}
If you are not already aware, getQualifiedClassName returns the string format of the class name. The regular expressions check specifically for the capital IInterfaceName styled string.
Lastly, if you know it's only one interface, you could simple just do this:
if ( componentType == IMyinterface ) {
trace( "component is a IMyinterface" );
}
After some careful trial and error, I've come up with the following function:
public static function isInterface(clazz:Class):Boolean
{
return describeType(clazz).factory.extendsClass.(#type=="Object").length()==0;
}
Does anyone know if this condition always holds true for all actionscript interfaces?
I think this will work for you:
getQualifiedSuperclassName(classObject);
This will return null if you pass an interface, as interfaces does not have a superclass. It will always give you ANY kind of result for a class, as every class is basically an Object :)
Anyway, I don't think that passing such mixed values to a function is a good idea ;) And checking if the class starts with "I" is worse (sorry Bennett :))
p.s.
Keep in mind that describeType is EXTREMELY slow!
I am new to visual c++, I have the following code:
ref class Book sealed
{
public:
Book(std::string title,std::string author,int year);
void setTitle(std::string title);
std::string getTitle() const;
int getYear() const;
void setYear(int year);
void setAuthor(std::string author_);
std::string getAuthor() const;
private:
std::string title_;
std::string author_;
int year_;
};
When I am trying to compile it I am getting the following error:
{ctor} signature of public member contains native type. I suppose this is because I am using an the std::string and not the Platform::String, how can I fix that?
Your ref class is not marked public itself, so it appears you are only consuming this class internally (as source) from other C++, and not intending for it to be published to other WinRT consumers.
If this is the case, you can set your constructor as internal instead of public, which will be public within this component and not visible externally. And really if that's your intended usage, then it can just be a regular 'class' instead of a 'ref class'. If you do wish to use it across the WinRT boundary but you don't need the constructor, you can make it a 'public ref class' and have the constructor marked as 'internal'. Kinda depends on your scenario.
If you instead wish to make this class public and have a public constructor which is usable across the WinRT boundary (so that it can be consumed by C#/VB/JS), then you need to use WinRT types (such as Platform::String). Within your class the storage type can still be a std::string (although I recommend using std::wstring, otherwise you need to do wide-to-narrow conversions, as Platform::Strings are wide strings).
To convert between these two types, use Platform::String::Data() to get at the underlying wchar_t* which you can use to construct a std::wstring. And similarly, Platform::String has a constructor which takes a wchar_t* (which you can get from std::wstring::c_str()).
You can't hold native types in a managed reference class.
You can only hold a pointer to an unmanaged object(a pointer is just a number after all, and that's why it's allowed).
This code seems to compile fine in the IDE, but the command-line compiler (SDK 4.5 mxmlc.exe) reports "Parameter initializer unknown or is not a compile-time constant."
senocular gives a good explanation and a maybe-workaround, but I'm hoping for something more elegent (like a command-line instruction).
package {
public class Constants {
public static const CONSTANT : int = 0;
}
}
package {
public interface IInterface {
function foo( param : int = Constants.CONSTANT ) : void;
}
}
package
{
public class Concrete implements IInterface
{
public function foo(param:int=Constants.CONSTANT):void
{
}
}
}
According to Senocular, it's all about the compilation order. There's no explicit way to set this order.
You could define inline constants using the define compiler option to avoid this problem.
Another way would be to create a library containing the constants. Libraries are included before user classes.
To create a library use the component compiler:
compc -output lib\Constants.swf -source-path src -include-classes Constants
When compiling the application, include that library:
mxmlc -include-libraries lib\Constants.swf -- src\Main.as
Just don't forget to recompile the library when the constants change, or use a build script that takes care of that.
A short comment on the example code:
The interface doesn't need to use that constant, any value will do and have the same effect on implementing classes.
Programming AS3 - Interfaces
A method that implements such a function declaration must have a default parameter value that is a member of the same data type as the value specified in the interface definition, but the actual value does not have to match.