C++遍历获得一个类的所有属性名,对该类的实例的所有属性的值 ...~~

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++遍历获得一个类的所有属性名,对该类的实例的所有属性的值 ...~~相关的知识,希望对你有一定的参考价值。

是利用反射吗?没有思路~~求指点,谢谢

参考技术A 不理解你说的什么意思,随便说一下……
把函数的借口改成引用或指针,把类中所有的属性通过借口传递出来。
参考技术B c++ 本身好像没有反射功能。估计实现不了。 参考技术C c++实现不了这种功能
编译后类就不存在了。
参考技术D .NET的反射机制是很有特色的,VB,C#,VC语言都支持。
通过反射机制,可以轻而易举枚举出一个类的各种信息,除了属性外,还可以获得构造器、方法、字段等各种信息,类型可以是公共的,非公共的,实例化的,静态的各种属性、方法等。
这里给出一段VC.NET的实例代码:
using namespace System;
using namespace System::Reflection;

//定义测试用的类 Student
public ref class Student

private:
String^ name;
Int32 number;
String^ address;

public:
Student(String^ name, String^ address, Int32 number)

this->name = name;
this->address = address;
this->number = number;


property String^ Name

String^ get()

return name;

void set(String^ value)

name = value;



property Int32 Number

Int32 get()

return number;

void set(Int32 value)

number = value;



protected:
property String^ Address

String^ get()

return address;

void set(String^ value)

address = value;


;

void DisplayPropertyInfo(Student^ student, array<PropertyInfo^>^ properties);
int main(array<System::String ^> ^args)

Student^ student = gcnew Student("Alice", "No.193, St.Robinson, NY, USA", 1);
student->Name = "Alice.Caley";
student->Number = 2;
Console::WriteLine(student->Name);
Console::WriteLine(student->Number);
Console::WriteLine();

//反射
Type^ type = student->GetType();

//公共实例属性
array<PropertyInfo^>^ publicProperties = type->GetProperties(static_cast<BindingFlags>(BindingFlags::Public | BindingFlags::Instance));
Console::WriteLine("[Display public property info]");
DisplayPropertyInfo(student, publicProperties);
Console::WriteLine();

//非公共实例属性
array<PropertyInfo^>^ nonPublicProperties =type->GetProperties(static_cast<BindingFlags>(BindingFlags::NonPublic | BindingFlags::Instance));
Console::WriteLine("[Display non public property info]");
DisplayPropertyInfo(student, nonPublicProperties);
Console::WriteLine();
return 0;


void DisplayPropertyInfo(Student^ student, array<PropertyInfo^>^ properties)

for (int i = 0; i < properties->Length; i++)

PropertyInfo^ p = properties[i];
Console::WriteLine(p->Name);
Console::WriteLine(p->PropertyType);

//获取student实例的属性值
Console::WriteLine("value -- " + p->GetValue(student, nullptr));

本回答被提问者采纳

java怎么获取src目录下所有的包名,类名,方法名 以及通过一个类名获得该类下的所有方法名

提供测试方法!

可以使用以下代码来获取src目录下所有的包名,类名,方法名 以及通过一个类名获得该类下的所有方法名。
import java.io.File;
import java.lang.reflect.Method;
public class LoopApp
public static void main(String[] args) throws Exception
String packageName = "";
File root = new File(System.getProperty("user.dir") + "\\src");
loop(root, packageName);

public static void loop(File folder, String packageName) throws Exception
File[] files = folder.listFiles();
for (int fileIndex = 0; fileIndex < files.length; fileIndex++)
File file = files[fileIndex];
if (file.isDirectory())
loop(file, packageName + file.getName() + ".");
else
listMethodNames(file.getName(), packageName);



public static void listMethodNames(String filename, String packageName)
try
String name = filename.substring(0, filename.length() - 5);
Object obj = Class.forName(packageName + name);
Method[] methods = obj.getClass().getDeclaredMethods();
System.out.println(filename);
for (int i = 0; i < methods.length; i++)
System.out.println("\t" + methods[i].getName());

catch (Exception e)
System.out.println("exception = " + e.getLocalizedMessage());


参考技术A /**
* 从包package中获取所有的Class
*
* @param pack
* @return
*/
public static Set<Class<?>> getClasses(Package pack)

// 第一个class类的集合
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
// 是否循环迭代
boolean recursive = true;
// 获取包的名字 并进行替换
String packageName = pack.getName();
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs;
try
dirs = Thread.currentThread().getContextClassLoader().getResources(
packageDirName);
// 循环迭代下去
while (dirs.hasMoreElements())
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol))
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findAndAddClassesInPackageByFile(packageName, filePath,
recursive, classes);
else if ("jar".equals(protocol))
// 如果是jar包文件
// 定义一个JarFile
JarFile jar;
try
// 获取jar
jar = ((JarURLConnection) url.openConnection())
.getJarFile();
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements())
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/')
// 获取后面的字符串
name = name.substring(1);

// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName))
int idx = name.lastIndexOf('/');
// 如果以"/"结尾 是一个包
if (idx != -1)
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx)
.replace('/', '.');

// 如果可以迭代下去 并且是一个包
if ((idx != -1) || recursive)
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class")
&& !entry.isDirectory())
// 去掉后面的".class" 获取真正的类名
String className = name.substring(
packageName.length() + 1, name
.length() - 6);
try
// 添加到classes
classes.add(Class
.forName(packageName + '.'
+ className));
catch (ClassNotFoundException e)
e.printStackTrace();





catch (IOException e)
e.printStackTrace();



catch (IOException e)
e.printStackTrace();


return classes;
/**
* 以文件的形式来获取包下的所有Class
*
* @param packageName
* @param packagePath
* @param recursive
* @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName,
String packagePath, final boolean recursive, Set<Class<?>> classes)
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory())
return;

// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter()
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file)
return (recursive && file.isDirectory())
|| (file.getName().endsWith(".class"));

);
// 循环所有文件
for (File file : dirfiles)
// 如果是目录 则继续扫描
if (file.isDirectory())
findAndAddClassesInPackageByFile(packageName + "."
+ file.getName(), file.getAbsolutePath(), recursive,
classes);
else
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
file.getName().length() - 6);
try
// 添加到集合中去
classes.add(Class.forName(packageName + '.' + className));
catch (ClassNotFoundException e)
e.printStackTrace();




追问

调用你这个方法的时候那个参数怎么构造? 构造package的时候需要4个参数 这4个分别是什么 你写个测试方案贴一些噻 谢谢

参考技术B 给你代码。
这个类直接放到eclipse中可以运行,

如果不是,
File root = new File(System.getProperty("user.dir") + "\\src");

改成你指写的src目录,其编译好的类也要在classpath中,才能运行。
---------------------------------------------------------------------------------------------------
import java.io.File;
import java.lang.reflect.Method;
public class LoopApp
public static void main(String[] args) throws Exception
String packageName = "";
File root = new File(System.getProperty("user.dir") + "\\src");
loop(root, packageName);

public static void loop(File folder, String packageName) throws Exception
File[] files = folder.listFiles();
for (int fileIndex = 0; fileIndex < files.length; fileIndex++)
File file = files[fileIndex];
if (file.isDirectory())
loop(file, packageName + file.getName() + ".");
else
listMethodNames(file.getName(), packageName);



public static void listMethodNames(String filename, String packageName)
try
String name = filename.substring(0, filename.length() - 5);
Object obj = Class.forName(packageName + name);
Method[] methods = obj.getClass().getDeclaredMethods();
System.out.println(filename);
for (int i = 0; i < methods.length; i++)
System.out.println("\t" + methods[i].getName());

catch (Exception e)
System.out.println("exception = " + e.getLocalizedMessage());


追问

你测试过吗? 为什么我测试的时候得不到方法名 而且我加上String packageName = ""; 这个包名之后就抛异常

追答

当然测试过了。

String packageName = "";

这个根本不用加内容,
在下边的loop方法里,通过递归目录来生成包名。
loop(file, packageName + file.getName() + ".");

我这里的flash版本过低,上传不了图片。
如果你不能执行,最大的可能就是找不到类。
应该 是我上面说的第二种。
你的classpath里找到不你寻找到的类的class文件。
你可以先把 listMethodNames 这块注掉,你看看你指定的目录下的java文件是不是都找到了。

这块正确了,在listMethodNames中通过反射实例化类。是最有可能出错的地方,原因就是
找到的这些java文件,编译好的class类,在你的classpath中找不到。
我不可能去解析java文件。

如果你这个类是放到eclipse里,什么也不用动就可以执行。
--------------------------------------------------------------------------------------
LoopApp.java
forName
forName
toString
isAssignableFrom
isInstance
getModifiers
isInterface
isArray
isPrimitive
getSuperclass
getComponentType
getName
asSubclass
cast
desiredAssertionStatus
getAnnotation
getAnnotations
getCanonicalName
getClassLoader
getClasses

还有,贴不下了。

追问

我制定的文件都找到了 调试了 但是方法名没有找到 我输出的结果和你的是一样的 我说的方法名是我自己类里面定义的方法名 而不是这些方法啊

追答

啊,不好意思 ,有一句写错了。
Object obj = Class.forName(packageName + name);

改成
Object obj = Class.forName(packageName + name).newInstance();

这样就行了

追问

你那样的话接口里面的方法找不到 会抛异常 我知道是怎么回事了Object obj = Class.forName(packageName + name);这里不要用Object 直接用Class这样的话得出来的就是我自己定义在类里面的方法。如果我只想找继承了某个类的类下面的方法我该怎么做判断咧?比如说我只想找继承了JFrame的类下面的方法

追答

if(obj instanceof JFrame)


加这个判断试一下。
--------------------------------------
回复 devil_yb:你改成 Class obj = Class.forName(packageName + name); 了吧,按我说的换成 Object obj = Class.forName(packageName + name).newInstance(); 或是 if(obj.newInstance() instanceof JFrame)
你再试一下。
------------------------------------------------------------------
回复 devil_yb:newInstance() 以后就是你自己类的了,不是JFrame的,我开始写的Class.forName(packageName + name); 这样得到的是Class而不是查找到的类,所以列出的方法不正确。
你按我上面说的试一下,不要我在这里说的,你还按你想的弄,这样,两岔去了,总也对不上。

追问

if(obj.newInstance() instanceof JFrame)这样得到JFrame里面的而不是extends JFrame的那个类里面的方法,Object obj = Class.forName(packageName + name).newInstance(); 这样做就全部抛异常了

追答

listMethodNames方法改成下边这样。

--------------------------------------------------------------------------------------------------------------
public void listMethodNames(String filename, String packageName)
try
String name = filename.substring(0, filename.length() - 5);
Object obj = Class.forName(packageName + name).newInstance();
if (!(obj instanceof JFrame))
return;

Method[] methods = obj.getClass().getDeclaredMethods();
System.out.println(filename);
for (int i = 0; i < methods.length; i++)
System.out.println("\t" + methods[i].getName());

catch (Exception e)
System.out.println("exception = " + e.getLocalizedMessage());



结果如下。
------------------------------------------------------------------------------------------------------------------
App.java
main
AppFrame.java
main
componentHidden
componentMoved
componentResized
componentShown

本回答被提问者采纳
参考技术C 这个可以用反射机制,
Class cls = Class.forName("包名.类名");
参考技术D 遍历枚举追问

我也知道大概是这样做 发代码啊

以上是关于C++遍历获得一个类的所有属性名,对该类的实例的所有属性的值 ...~~的主要内容,如果未能解决你的问题,请参考以下文章

C#获取实体类属性名和值

oop典型应用,代码。

单例模式C++实现

设计模式之单例模式C++实现

java-反射

反射技术