2016-08-02 69 views
1

我將使用C作爲示例語言來展示我的意思。變量類型本身是變量的語言?

struct parent 
{ 
    int x; 
    char y; 
}; 
struct child 
{ 
    char y; 
    int x; 
}; 

int foo(void * s, type obj_type) 
{ 
    // the casting is done using a "type" variable 
    obj_type obj = (obj_type) s; 
    return obj->x; 
} 

int main(int argc, char** argv) 
{ 
    type obj_type = struct parent *; 
    struct parent p; 
    p.x = 0; 

    //returns 0 
    foo(&p, obj_type); 

    obj_type = struct child *; 
    struct child c; 
    c.x = 5; 

    // returns 5 
    foo(&c, obj_type); 

    return 0; 
} 

正如你可以看到,x被放置在不同的位置在內存中的兩種結構,所以我不能只是有一個靜態內存偏移。無論如何,這在C中是否可能?(我想不出來的一些預處理器魔法)?我假設不是,但是有沒有哪些語言可以將類型本身用作變量?我很想探索以類型爲中心的編程的含義

編輯:正如itsme86所指出的,C#具有Type類的這種能力。此外,C++概念和Haskell類型類也很有用。

+0

我不認爲我遵循你的要求。你想'返回obj-> x;'返回'int'? –

+0

是的。儘管取決於類型運算符,obj-> x可能位於obj的地址處,或者可能是1個字節的偏移量(給定結構設置)。我想要的是一個可用於識別類型而非值的變量 – m1cky22

+3

您正在尋找的功能是[類型自省](https://en.wikipedia.org/wiki/Type_introspection)。它在一些面向對象的語言中可用,但在C中不可用(儘管可以通過將「類型」成員添加爲所有結構的第一個成員來破解它)。 – user3386109

回答

2

如果離開類型安全的背後,你可以使用offsetof(從stddef.h):

int foo(unsigned char * s, size_t offset) 
{ 
    int* ptr = (int*)(s + offset); 
    return *ptr; 
} 

foo((unsigned char*)&p, offsetof(struct parent, x)); 

但我真的不能推薦它。

+0

這絕對是一種獲得我期待的有趣結果的方法。然而,我問的主要原因是因爲我想知道變量類型是否可以包含類型作爲它們的值,即「type t = int」。這是可能的任何語言? – m1cky22

0

在Java中,您可以通過反射API訪問類型信息。下面是一個例子:

package stackoverflow; 

import java.util.Arrays; 

public class MyClass { 
    public static void main(String[] args) { 
     MyClass myInstance = new MyClass(42, "foo"); 
     Class<MyClass> myClass = MyClass.class; 
     System.out.println(myInstance instanceof MyClass); 
     System.out.println(myInstance.getClass().equals(myClass)); 
     System.out.println(myClass.getName()); 
     System.out.println(Arrays.toString(myClass.getDeclaredFields())); 
     System.out.println(Arrays.toString(myClass.getDeclaredMethods())); 
    } 

    private final int i; 
    private final String s; 

    public MyClass(int i, String s) { 
     this.i = i; 
     this.s = s; 
    } 

    public int getI() { 
     return i; 
    } 

    public String getS() { 
     return s; 
    } 
} 

輸出:

true 
true 
stackoverflow.MyClass 
[private final int stackoverflow.MyClass.i, private final java.lang.String stackoverflow.MyClass.s] 
[public int stackoverflow.MyClass.getI(), public java.lang.String stackoverflow.MyClass.getS(), public static void stackoverflow.MyClass.main(java.lang.String[])] 

正如你可以看到,MyClass.class是一般類型java.lang.Class<T>,其提供關於類MyClass獲取信息的一個對象。該對象也可以通過類的任何實例檢索,請參閱myInstance.getClass()。我列舉了幾個例子來展示什麼是可訪問的。您還可以通過其Class對象創建類的新實例。欲瞭解更多信息,你可能也想看看java.lang.reflect包的Javadoc。


請注意,這隻允許您訪問這些信息。例如,它不允許您更改現有實例的類型,我認爲這是一件好事。然而,這似乎是可能的在Python中:

Can I dynamically convert an instance of one class to another?