I am having problem with getting the class names of all classes which are inherited from a base class.
Class Base
{
};
Class A:public Base
{
};
Class B:public Base
{
};
Class C:public Base
{
};
.....so on. My requirement is that I want to know all the class names which are inherited from class Base. Is there any way or method from base class that I can know all the classes? Thanks in advance.
Qt allows to do this with the following limitations:
All involved classes should be derived from QObject.
Each class should be registered in a global class list. Qt doesn't provide a way to get full list of classes.
Meta information about a QObject-derived class is stored in a QMetaObject that can be accessed via T::staticMetaObject. First of all, you want to have a list of all metaobjects in your application. You can use something like this:
QList<const QMetaObject*> global_list;
template<class T> register_class() {
global_list << &T::staticMetaObject;
}
//execute the following at program initialization
register_class<Base>();
register_class<A>();
register_class<B>();
register_class<C>();
To get list of class names derived from Base, you need to:
Get const QMetaObject* of the target class as &Base::staticMetaObject.
Iterate over global list of metaobjects and check if QMetaObject::​superClass returns target meta object. You may need to perform recursive check if indirect inheritance should also be detected.
Get names of found subclasses with QMetaObject::​className.
Related
I know that dynamic libraries can be loaded by Poco::SharedLibrary as below:
using PocoLibraryPtr = std::shared_ptr<Poco::SharedLibrary>;
poco_library = PocoLibraryPtr(new Poco::SharedLibrary(library_path));
I see in the code that the class is instantiated directly after loading. Is this feasible? Currently this code works fine.
template <typename ClassObject, typename Base>
class ClassFactory : public AbstractClassFactory<Base> {
public:
ClassFactory(const std::string& class_name,
const std::string& base_class_name)
: AbstractClassFactory<Base>(class_name, base_class_name) {}
Base* CreateObj() const { return new ClassObject; }
};
When the class is loaded, then the code use
classobj = factory->CreateObj();
to create the class. I did not find similar usage online. Is there any code I didn't notice?
It looks like you want a shared library to create an object using a templatized factory class.
Template instantiations are static polymorphic so the factory object needs to be determined at compile time.
In other words, no, that won't work.
If you specifically want Poco SharedLibrary help, take a look at the Poco documentation for more help: https://pocoproject.org/docs/Poco.SharedLibrary.html.
Or look at the slides here: https://pocoproject.org/slides/120-SharedLibraries.pdf
I have a Kotlin class whose primary (and only) constructor is empty.
I have a reference to this class:
val kClass: KClass<MyClass> = MyClass::class
How do I create an instance of this class using reflection?
In Java I would do myClass.newInstance() but it seems in Kotlin I need to find the constructor first:
kClass.constructors.first().call()
I have seen mention of primaryConstructor in some bug reports but it's not showing up in my IDE.
In your case, Java reflection might be enough: you can use MyClass::class.java and create a new instance in the same way as you would with Java reflection (see #IngoKegel's answer).
But in case there's more than one constructor and you really need to get the primary one (not the default no-arg one), use the primaryConstructor extension function of a KClass<T>. It is a part of Kotlin reflection, which is not shipped within kotlin-stdlib.
To use it, you have to add kotlin-reflect as a dependency, e.g. a in Gradle project:
dependencies {
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
Assuming that there is ext.kotlin_version, otherwise replace $kotlin_version with the version you use.
Then you will be able to use primaryConstructor, for example:
fun <T : Any> construct(kClass: KClass<T>): T? {
val ctor = kClass.primaryConstructor
return if (ctor != null && ctor.parameters.isEmpty())
ctor.call() else
null
}
You can use the Java class to create new instance:
MyClass::class.java.newInstance()
For those checking this question now, since Kotlin 1.1 there's also createInstance() extension method on KClass
Much like the accepted answer, this function works only in case class has an empty constructor or constructor with all default arguments.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect.full/create-instance.html
Expanding on Alexeys Answer, to include a primary constructor call with parameters:
/* Example class with no-args constructor */
class MyClass
/* Example class requiring parameters */
class MyClassWithParams(parameter1: String, parameter2: MyClass)
val myKClass: KClass<MyClass> = MyClass::class
val myKClassWithParameters: KClass<MyClassWithParams> = MyClassWithParams::class
/* We can create an object by calling createInstance when no constructor parameters are required as explained in other answers. */
val myObject: MyClass = myKClass.createInstance()
/* To create an object with parameters, we need to get the constructor first, and call it with the parameters instead, similarly to how we would do in Java. */
val myObjectWithParameters: MyClassWithParams? =
myKClassWithParameters.primaryConstructor?.call(
"StringParameter", myObject
)
I am tryng to use a global class from my main in another class and it is not working out...
PilhaJogo p[7]; //these are my global classes
PilhaSaida s[4];
Card v[60];
PilhaDescarte d;
PilhaEstoque e;
This is the function from PilhaDescarte I am trying to use.
void Discard(){
setTopo(getTopo()+1);
v[getTopo()].aberta=true;
}
This is the header of the class I am trying to use Discard on:
#include<Card.h>
#include<PilhaDescarte.h>
#include<PilhaJogo.h>
#include<PilhaSaida.h>
#include<Global.h>
using namespace std;
class PilhaJogo;
class PilhaDescarte;
class PilhaSaida;
class PilhaEstoque
And here is where the error occurs... :
void Compra(){
v[getTopo()+1];
d.Discard();
}
I don't know how to use global variable that are classes in other classes.
And I did initialize all the classes in the main:
for(i=0;i<60;i++){
v[i].nome="0";
}
for(i=0;i<4;i++){
s[i].setStatus(false);
}
for(i=0;i<7;i++){
p[i].Inicia(0+4*i,i);
}
d.setBase(0);
d.setTopo(0);
d.Inicia();
I am trying to understand yet, but try to get a look at good manners for C++ programming, because there are some changes you need to do. At first you need to initialize the variables at the constructor and try to get a look about encapsulation, we can't set variables to public. =)
If you want, there is this awesome book (brazilian portuguese):
http://www.cesarkallas.net/arquivos/apostilas/programacao/c_c%2B%2B/ApostilaProgramacaoCppv045.pdf
I am brazilian, I think you are too because of the variables names.
I am attempting to determine which classes are subclassed from several different types. For example, if E1 extends A, E2 extends A, and E3 extends B, I want to find all classes that are subclassed from A and return a list of the types E1 and E2. These types are registered with the QMetaSystem.
My first attempt was to iterate over the user declared types, instantiate it, and get the superClass name:
int type = QMetaType::User;
while( QMetaType::isRegistered(type) ) {
QObject *o = (QObject*)QMetaType::construct(type);
QString parent = o->metaObject()->superClass()->className();
}
This seemed like a bad idea when I wrote it and didn't expect it to work. Unsurprisingly, it segfaults when attempting to get the metaObject.
Is it possible to get the information I need from the QMetaType or is there another way of getting this information?
Update
The problem seems to be in trying to iterate over all the user types. Before I register my types, some Qt type seem to be getting registered before mine. Specifically, the two registered types are QPaintBufferCacheEntry (typeId = 256) and QPaintBufferCacheEntryV2 (typeId = 257). I can initialize the object just fine, but it crashes when I attempt to get the meta object, so I'm thinking the cast is illegal. I'm not quite sure where these are being registered because my code base is not doing it explicitly.
I took this to mean that it just wasn't safe to iterate over and construct each of the user types.
Your idea is correct. This should give you the name of the parent class:
QObject *o = (QObject*)QMetaType::construct(type);
QString parent = o->metaObject()->superClass()->className();
For it to work, your classes must have been declared with Q_DECLARE_METATYPE(Type) and registered with qRegisterMetaType(). This is the case as QMetaType::isRegistered(type) is true.
Your user defined classes must also inherits from QObject (directly or not) and have the Q_OBJECT macro in their definition. This could explain your segfault.
superClass() can also return 0 if there is no parent class, but here all your classes should at least inherit QObject.
There is also QObject::inherits(const char * className) to know if an object is of a class inheriting, even indirectly, from className.
I've got an object declared and instantiated in my Flex application's singular MXML file:
public var CDN:CDNClass = new CDNClass;
I would like to access this same CDN object (and its public methods and properties) in another class declared in a separate .as file as such:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
But when I try to access the public method parsePlayList in the CDN object in a method in the class defined in the .as file, I get the following error:
Access of undefined property CDN
The reason I want to do this is to break up the logic of my application into multiple AS files and have minimal MXML files, probably only one.
Thanks - any help is much appreciated. Perhaps my OOD/OOP thinking is not correct here?
IT depends on your class architecture. For your code to work, the CDNClass instance must be defined and implemented inside your SyncConnectorManager.
Generally, you can always call down into components, but should never call up
One option is to pass the instance ofCDNClass to a variable inside SyncConnectorManager. Add this variable to your SyncConnectionManager class:
public var CDN:CDNClass = new CDNClass;
And at some point do this:
syncConnectorManagerInstance.CDN = CDN;
That way both classes will have access to the same CDN instance and can call methods on it.
Yes, your OOP thinking is not correct here. You should take in mind differences between classes and instances. This line declares a filed in a current class and initiates it with an instance:
public var CDN:CDNClass = new CDNClass;
So current instance of your MXML class (you can think about it as usual AS class with some other notation) has public field. To operate with CDN instance you need something from the following:
Read the value of CDN (as far as it is public) from the instance of your MXML class. You need some reference to it for that.
The instance of your MXML class can have a reference to the instance of SyncConnectorManager and SyncConnectorManager should have a way to inject the value of CDN there. Something like:
Your class:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private var CDN:CDNClass;
public function SyncConnectorManager(CDN:CDNClass)
{
this.CDN = CDN;
}
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
In your case SyncConnectorManager class hasn't CDN declared (the problem of the compiler error you mentioned) and instantiated (the problem of NPE even if you just declare field).
As the bottom line I can suggest you to follow ActionScript naming and coding conventions to talk other people and team members about your code :)