看正月初一是什么生肖| 维生素c什么时候吃最好| 怕冷的人是什么原因| 一柱擎天什么意思| 皮肤越抓越痒是什么原因| 肚子有水声是什么原因| 胃酸吃什么药好| 什么是二型糖尿病| 柿子不能跟什么一起吃| 为什么肚子总是胀胀的| 肝虚吃什么中成药| 产后42天复查都检查什么| 什么家欢乐| 身份证上的数字是什么字体| 6.28什么星座| 丁未年五行属什么| 皮肤长小肉粒是什么原因| 什么是介入手术| 己亥是什么意思| 孩提是什么意思| 人为什么要穿衣服| 微商是什么意思| 94狗跟什么属相配最好| 1955属什么生肖| 什么的跑步| 什么叫双向情感障碍| 女人喝黄连有什么好处| 大便恶臭是什么原因| 阿昔洛韦片治什么病| 枭神夺食会发生什么| 没睡好头疼是什么原因| 云吞是什么| 左边是心脏右边是什么| 柿子不能和什么食物一起吃| 对什么有好处的英文| 钙化积分是什么意思| 蚂蚁为什么要搬家| 牙龈长泡是什么原因| 尿道灼热感吃什么药| 小候鸟是什么意思| 14年婚姻是什么婚| 每天一杯蜂蜜水有什么好处| 多发性脂肪瘤是什么原因造成的| 齁是什么意思| 月经前腰疼的厉害是什么原因| 琥珀是什么颜色| 为什么拉屎是黑色的| 检查胸部挂什么科| 改姓需要什么手续| 自愈什么意思| 百合有什么作用与功效| 心脏供血不足用什么药| 口干是什么病| 皮笑肉不笑是什么生肖| 嘴唇不红润是什么原因| 动脉抽血是做什么检查| 青羊药片有什么功效| 月经颜色暗红色是什么原因| 为什么不建议年轻人做肠镜| 张柏芝什么星座| 感冒为什么会全身酸痛无力| w代表什么单位| 内膜厚是什么原因引起的| 火龙果有什么好处| 驱除鞑虏是什么意思| 一到晚上就饿什么原因| 血肿是什么意思| 什么多么什么造句| dollars是什么意思| 杀鸡吓什么| 超霸是什么意思| 下肢浮肿是什么原因| 红豆配什么打豆浆好喝| 梦见老公怀孕什么预兆| 社保跟医保有什么区别| 甲减对胎儿有什么影响| 什么是面瘫| 潆是什么意思| 为什么有的人晒不黑| 酷暑是什么意思| 4月10号是什么星座| 血压高喝什么茶| 人突然瘦了要检查什么| 尾椎骨痛挂什么科| 长期喝咖啡有什么好处和坏处| od值是什么意思| 为什么夏天吃姜好| 才华横溢是什么意思| 宫颈那囊什么意思| 985大学是什么意思| 摘帽是什么意思| 傲慢什么意思| 鲱鱼罐头那么臭为什么还有人吃| 狗为什么喜欢吃屎| 肉桂跟桂皮有什么区别| 正在值机是什么意思| 暖气是什么意思| 后会无期什么意思| 为什么喜欢秋天| 急性乳腺炎是什么原因引起的| t代表什么| 姑姑叫我什么| 什么水果维生素c含量最高| 心脏搭桥后最怕什么| 重阳节送老人什么礼物| 排骨炖什么汤好喝| 帕金森是什么原因引起的| 菊花茶泡了为什么会变绿| 炸酱面用什么酱| 甲减检查什么项目| poppy是什么意思| 三元及第是什么意思| 什么东西啊| 有胃火口臭怎么办吃什么药| 桂花树施什么肥| 牙疼吃什么止疼药| 嘴唇干燥是什么原因引起的| 舅舅的舅舅叫什么| 右下腹疼是什么原因| 山茶花什么时候开| 娇滴滴是什么意思| 用纸盒能做什么手工| 脸上长痘痘用什么药膏效果好| 御字五行属什么| 三魂七魄是什么| 检查脖子挂什么科| 吃姜对身体有什么好处| 射手座和什么座最配| 氯化钾是什么东西| 走路气喘是什么原因| 脾胃虚弱吃什么药调理| 考研是什么时候考| 一直腹泻是什么原因| 月牙消失了是什么原因| 肾小球滤过率是什么意思| 公因数是什么意思| 嗓子疼喝什么药| 公积金有什么作用| 蜱虫咬人后有什么症状图片| 城隍庙是什么神| 为什么小孩子有白头发| 白细胞低是什么原因引起的| 为什么会长癣| 什么是排卵期| 扁桃体疼吃什么药| 低血糖的症状是什么| 小孩肚脐眼周围疼是什么原因| ufo是什么| 收官之作什么意思| 骨质增生吃什么药最好| 耗儿鱼是什么鱼| 厌氧菌感染用什么药| 什么是光| 白蚂蚁长什么样子图片| 什么喷剂延时最好| 家庭出身是什么| 梦见苹果是什么意思| 纹身有什么危害| 亲子鉴定需要什么材料| 心律不齐吃什么药好| 淋巴结回声是什么意思| 排长是什么级别| 百合有什么功效| 混合性皮肤用什么护肤品比较好| 器皿是什么意思| 心肌酶是什么意思| 上将是什么级别| 杏色配什么颜色最洋气| 碳酸盐是什么| 阳痿什么症状| 有偿服务是什么意思| 蚊子长什么样| 东字五行属什么| 藏在我回忆里的那个人什么歌| 生理年龄是什么意思| 胆红素高吃什么食物能降得快| 出生医学证明有什么用| 什么是孝顺| 议员在中国相当于什么| 药剂科是干什么的| cpr是什么意思| 电磁炉滴滴响不加热是什么原因| 植物神经紊乱吃什么中成药| 痹症是什么意思| 夏天爱出汗是什么原因| 拾掇是什么意思| 尾货是什么意思| 低血压要注意些什么| 孩子高烧不退是什么原因| 甲状腺滤泡性肿瘤是什么意思| 商鞅姓什么| 人活在世上的意义是什么| 电视开不了机是什么原因| 西湖醋鱼用什么鱼| 骨折什么症状| 屎壳郎的学名叫什么| 什么是政策| 白蛋白偏低是什么意思| 吃葵花籽有什么好处和坏处吗| 上午十点多是什么时辰| 鼻子出血是什么原因| 尿胆原阴性是什么意思| 铅超标吃什么排铅| crp高是什么感染| 斑鸠和鸽子有什么区别| 什么降肌酐| 10月5号是什么星座| 爱慕内衣什么档次| only是什么品牌| 康复科是主要治疗什么| 手指甲白是什么原因| 云肖是什么生肖| lyocell是什么面料| 纪年是什么意思| 怀孕药流吃什么药| 黑匣子什么颜色| 养血清脑颗粒治什么病| 6月2日什么星座| 晴空万里什么意思| 眼睛的睛可以组什么词| 什么是室性早搏| 杏子不能和什么一起吃| 肋间神经痛用什么药| 弱的部首是什么| 爆菊什么意思| 吃干饭是什么意思| 鸡属相和什么属相最配| 醍醐灌顶什么意思| 变化无常的意思是什么| 髋关节积液是什么原因造成的| 便溏是什么意思| 5月9日是什么星座| 吃什么能排毒体内毒素| 12月21日是什么星座| 嘴唇麻木什么病兆| 传教士是什么意思| 天丝是什么面料| 超声波是什么| 喝酒对身体有什么好处和坏处| 98年一月属什么生肖| 炖羊排放什么调料好吃| 小苏打学名叫什么| 血糖高了会有什么危害| 腿麻是什么原因| 腰椎退行性改变什么意思| 刘亦菲是什么星座| 昕五行属什么| 什么除草剂三年不长草| 一吃东西就牙疼是什么原因引起的| 起鸡皮疙瘩是什么原因| 尿培养能查出什么病| 学考是什么| 什么叫哮喘| 秋天有什么花| 女人绝经后靠什么排毒| 脑供血不足吃什么中药| 鼻窦炎是什么原因引起的呢| 蔗糖脂肪酸酯是什么| 气血两虚是什么意思| 上海市委书记什么级别| 转注是什么意思| 甙是什么意思| 指奸是什么意思| 隐翅虫皮炎用什么药膏| 百度Jump to content

第五届上海国际木偶艺术节闭幕 中俄两大剧目勇夺最佳

From Wikipedia, the free encyclopedia
百度 上赛季,他中超出场19次,大部分是替补登场。

In computer science, dynamic dispatch is the process of selecting which implementation of a polymorphic operation (method or function) to call at run time. It is commonly employed in, and considered a prime characteristic of, object-oriented programming (OOP) languages and systems.[1]

Object-oriented systems model a problem as a set of interacting objects that enact operations referred to by name. Polymorphism is the phenomenon wherein somewhat interchangeable objects each expose an operation of the same name but possibly differing in behavior. As an example, a File object and a Database object both have a StoreRecord method that can be used to write a personnel record to storage. Their implementations differ. A program holds a reference to an object which may be either a File object or a Database object. Which it is may have been determined by a run-time setting, and at this stage, the program may not know or care which. When the program calls StoreRecord on the object, something needs to choose which behavior gets enacted. If one thinks of OOP as sending messages to objects, then in this example the program sends a StoreRecord message to an object of unknown type, leaving it to the run-time support system to dispatch the message to the right object. The object enacts whichever behavior it implements.[2]

Dynamic dispatch contrasts with static dispatch, in which the implementation of a polymorphic operation is selected at compile time. The purpose of dynamic dispatch is to defer the selection of an appropriate implementation until the run time type of a parameter (or multiple parameters) is known.

Dynamic dispatch is different from late binding (also known as dynamic binding). Name binding associates a name with an operation. A polymorphic operation has several implementations, all associated with the same name. Bindings can be made at compile time or (with late binding) at run time. With dynamic dispatch, one particular implementation of an operation is chosen at run time. While dynamic dispatch does not imply late binding, late binding does imply dynamic dispatch, since the implementation of a late-bound operation is not known until run time.[citation needed]

Mechanisms

[edit]

Single and multiple dispatch

[edit]

The choice of which version of a method to call may be based either on a single object, or on a combination of objects. The former is called single dispatch and is directly supported by common object-oriented languages such as Smalltalk, C++, Java, C#, Objective-C, Swift, JavaScript, and Python. In these and similar languages, one may call a method for division with syntax that resembles

dividend.divide(divisor)  # dividend / divisor

where the parameters are optional. This is thought of as sending a message named divide with parameter divisor to dividend. An implementation will be chosen based only on dividend's type (perhaps rational, floating point, matrix), disregarding the type or value of divisor.

By contrast, some languages dispatch methods or functions based on the combination of operands; in the division case, the types of the dividend and divisor together determine which divide operation will be performed. This is known as multiple dispatch. Examples of languages that support multiple dispatch are Common Lisp, Dylan, and Julia.

Dynamic dispatch mechanisms

[edit]

A language may be implemented with different dynamic dispatch mechanisms. The choices of the dynamic dispatch mechanism offered by a language to a large extent alter the programming paradigms that are available or are most natural to use within a given language.

Normally, in a typed language, the dispatch mechanism will be performed based on the type of the arguments (most commonly based on the type of the receiver of a message). Languages with weak or no typing systems often carry a dispatch table as part of the object data for each object. This allows instance behaviour as each instance may map a given message to a separate method.

Some languages offer a hybrid approach.

Dynamic dispatch will always incur an overhead so some languages offer static dispatch for particular methods.

C++ implementation

[edit]

C++ uses early binding and offers both dynamic and static dispatch. The default form of dispatch is static. To get dynamic dispatch the programmer must declare a method as virtual.

C++ compilers typically implement dynamic dispatch with a data structure called a virtual function table (vtable) that defines the name-to-implementation mapping for a given class as a set of member function pointers. This is purely an implementation detail, as the C++ specification does not mention vtables. Instances of that type will then store a pointer to this table as part of their instance data, complicating scenarios when multiple inheritance is used. Since C++ does not support late binding, the virtual table in a C++ object cannot be modified at runtime, which limits the potential set of dispatch targets to a finite set chosen at compile time.

Type overloading does not produce dynamic dispatch in C++ as the language considers the types of the message parameters part of the formal message name. This means that the message name the programmer sees is not the formal name used for binding.

Go, Rust and Nim implementation

[edit]

In Go, Rust and Nim, a more versatile variation of early binding is used. Vtable pointers are carried with object references as 'fat pointers' ('interfaces' in Go, or 'trait objects' in Rust[3][4]).

This decouples the supported interfaces from the underlying data structures. Each compiled library needn't know the full range of interfaces supported in order to correctly use a type, just the specific vtable layout that they require. Code can pass around different interfaces to the same piece of data to different functions. This versatility comes at the expense of extra data with each object reference, which is problematic if many such references are stored persistently.

The term fat pointer simply refers to a pointer with additional associated information. The additional information may be a vtable pointer for dynamic dispatch described above, but is more commonly the associated object's size to describe e.g. a slice.[citation needed]

Smalltalk implementation

[edit]

Smalltalk uses a type-based message dispatcher. Each instance has a single type whose definition contains the methods. When an instance receives a message, the dispatcher looks up the corresponding method in the message-to-method map for the type and then invokes the method.

Because a type can have a chain of base types, this look-up can be expensive. A naive implementation of Smalltalk's mechanism would seem to have a significantly higher overhead than that of C++ and this overhead would be incurred for every message that an object receives.

Real Smalltalk implementations often use a technique known as inline caching[5] that makes method dispatch very fast. Inline caching basically stores the previous destination method address and object class of the call site (or multiple pairs for multi-way caching). The cached method is initialized with the most common target method (or just the cache miss handler), based on the method selector. When the method call site is reached during execution, it just calls the address in the cache. (In a dynamic code generator, this call is a direct call as the direct address is back patched by cache miss logic.) Prologue code in the called method then compares the cached class with the actual object class, and if they don't match, execution branches to a cache miss handler to find the correct method in the class. A fast implementation may have multiple cache entries and it often only takes a couple of instructions to get execution to the correct method on an initial cache miss. The common case will be a cached class match, and execution will just continue in the method.

Out-of-line caching can also be used in the method invocation logic, using the object class and method selector. In one design, the class and method selector are hashed, and used as an index into a method dispatch cache table.

As Smalltalk is a reflective language, many implementations allow mutating individual objects into objects with dynamically generated method lookup tables. This allows altering object behavior on a per object basis. A whole category of languages known as prototype-based languages has grown from this, the most famous of which are Self and JavaScript. Careful design of the method dispatch caching allows even prototype-based languages to have high-performance method dispatch.

Many other dynamically typed languages, including Python, Ruby, Objective-C and Groovy use similar approaches.

Examples

[edit]

C++

[edit]
import std;

// make Pet an abstract virtual base class
class Pet {
protected:
    std::string name;
public:
    Pet(const std::string& name):
        name{name} {}

    virtual void speak() = 0;
};

class Dog : public Pet {
public:
    Dog(const std::string& name):
        Pet(name) {}

    void speak() override {
        std::println("{} says 'Woof!'", name);
    }
};

class Cat : public Pet {
public:
    Cat(const std::string& name):
        Pet(name) {}

    void speak() override {
        std::println("{} says 'Meow!'", name);
    }
};

// speak() will be able to accept anything deriving from Pet
void speak(Pet& pet) {
    pet.speak();
}

int main() {
    Dog fido("Fido");
    Cat simba("Simba");
    speak(fido);
    speak(simba);
    return 0;
}

Java

[edit]
abstract class Pet {
    protected String name;

    public Pet(String name) {
        this.name = name;
    }

    public abstract void speak();
}

class Dog extends Pet {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void speak() {
        System.out.printf("%s says 'Woof!'%n", name);
    }
}

class Cat extends Pet {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void speak() {
        System.out.printf("%s says 'Meow!'%n", name);
    }
};

public class Main {
    public static void speak(Pet pet) {
        pet.speak();
    }

    public static void main(String[] args) {
        Dog fido = new Dog("Fido");
        Cat simba = new Cat("Simba");
        speak(fido);
        speak(simba);
    }
}

Python

[edit]
from abc import ABC, abstractmethod
from typing import Never

# ABC is a class used to denote that classes directly extending it are abstract
class Pet(ABC):
    def __init__(self, name: str) -> None:
        self.name = name

    @abstractmethod
    def speak(self) -> Never:
        raise NotImplementedError("Abstract method must be implemented by derived classes")

class Dog(Pet):
    def __init__(self, name: str) -> None:
        super.__init__(name)

    def speak(self) -> None:
        print(f"{self.name} says 'Woof!'")

class Cat(Pet):
    def __init__(self, name: str) -> None:
        super.__init__(name)

    def speak(self) -> None:
        print(f"{self.name} says 'Meow!'")

def speak(pet: Pet) -> None:
    # Dynamically dispatches the speak method
    # pet can either be an instance of Dog or Cat
    pet.speak()

if __name__ == "__main__":
    fido: Dog = Dog("Fido")
    speak(dog)
    simba: Cat = Cat("Simba")
    speak(cat)

Rust

[edit]
trait Pet {
    fn speak(&self);
}

struct Dog<'a> {
    name: &'a str
}

struct Cat<'a> {
    name: &'a str
}

impl<'a> Dog<'a> {
    fn new(name: &'a str) -> Self {
        Dog { name }
    }
}

impl<'a> Cat<'a> {
    fn new(name: &'a str) -> Self {
        Cat { name }
    }
}

impl Pet<'a> for Dog<'a> {
    fn speak(&self) {
        println!("{} says 'Woof!'", self.name);
    }
}

impl Pet<'a> for Cat<'a> {
    fn speak(&self) {
        println!("{} says 'Meow!'", self.name);
    }
}

// speak() uses dynamic dispatch and resolves the type at runtime,
// for any type that implements the trait Pet
fn speak(pet: &dyn Pet) {
    pet.speak();
}

fn main() {
    let fido: Dog = Dog::new("Fido");
    let simba: Cat = Cat::new("Simba");
    speak(&fido);
    speak(&simba);
}

See also

[edit]

References

[edit]
  1. ^ Milton, Scott; Schmidt, Heinz W. (1994). Dynamic Dispatch in Object-Oriented Languages (Technical report). Vol. TR-CS-94-02. Australian National University. CiteSeerX 10.1.1.33.4292.
  2. ^ Driesen, Karel; H?lzle, Urs; Vitek, Jan (1995). "Message Dispatch on Pipelined Processors". ECOOP’95 — Object-Oriented Programming, 9th European Conference, ?arhus, Denmark, August 7–11, 1995. Lecture Notes in Computer Science. Vol. 952. Springer. CiteSeerX 10.1.1.122.281. doi:10.1007/3-540-49538-X_13. ISBN 3-540-49538-X.
  3. ^ Klabnik, Steve; Nichols, Carol (2023) [2018]. "17. Object-oriented programming features". The Rust Programming Language (2 ed.). San Francisco, California, USA: No Starch Press, Inc. pp. 375–396 [379–384]. ISBN 978-1-7185-0310-6. p. 384: Trait objects perform dynamic dispatch […] When we use trait objects, Rust must use dynamic dispatch. The compiler doesn't know all the types that might be used with the code that's using trait objects, so it doesn't know which method implemented on which type to call. Instead, at runtime, Rust uses the pointers inside the trait object to know which method to call. This lookup incurs a runtime cost that doesn't occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a method's code, which in turn prevents some optimizations. (xxix+1+527+3 pages)
  4. ^ "Trait objects". The Rust Reference. Retrieved 2025-08-06.
  5. ^ Müller, Martin (1995). Message Dispatch in Dynamically-Typed Object-Oriented Languages (Master thesis). University of New Mexico. pp. 16–17. CiteSeerX 10.1.1.55.1782.

Further reading

[edit]
  • Lippman, Stanley B. (1996). Inside the C++ Object Model. Addison-Wesley. ISBN 0-201-83454-5.
  • Groeber, Marcus; Di Geronimo, Jr., Edward "Ed"; Paul, Matthias R. (2025-08-06) [2025-08-06]. "GEOS/NDO info for RBIL62?". Newsgroupcomp.os.geos.programmer. Archived from the original on 2025-08-06. Retrieved 2025-08-06. […] The reason Geos needs 16 interrupts is because the scheme is used to convert inter-segment ("far") function calls into interrupts, without changing the size of the code. The reason this is done so that "something" (the kernel) can hook itself into every inter-segment call made by a Geos application and make sure that the proper code segments are loaded from virtual memory and locked down. In DOS terms, this would be comparable to an overlay loader, but one that can be added without requiring explicit support from the compiler or the application. What happens is something like this: […] 1. The real mode compiler generates an instruction like this: CALL <segment>:<offset> -> 9A <offlow><offhigh><seglow><seghigh> with <seglow><seghigh> normally being defined as an address that must be fixed up at load time depending on the address where the code has been placed. […] 2. The Geos linker turns this into something else: INT 8xh -> CD 8x […] DB <seghigh>,<offlow>,<offhigh> […] Note that this is again five bytes, so it can be fixed up "in place". Now the problem is that an interrupt requires two bytes, while a CALL FAR instruction only needs one. As a result, the 32-bit vector (<seg><ofs>) must be compressed into 24 bits. […] This is achieved by two things: First, the <seg> address is encoded as a "handle" to the segment, whose lowest nibble is always zero. This saves four bits. In addition […] the remaining four bits go into the low nibble of the interrupt vector, thus creating anything from INT 80h to 8Fh. […] The interrupt handler for all those vectors is the same. It will "unpack" the address from the three-and-a-half byte notation, look up the absolute address of the segment, and forward the call, after having done its virtual memory loading thing... Return from the call will also pass through the corresponding unlocking code. […] The low nibble of the interrupt vector (80h–8Fh) holds bit 4 through 7 of the segment handle. Bit 0 to 3 of a segment handle are (by definition of a Geos handle) always 0. […] all Geos API run through the "overlay" scheme […]: when a Geos application is loaded into memory, the loader will automatically replace calls to functions in the system libraries by the corresponding INT-based calls. Anyway, these are not constant, but depend on the handle assigned to the library's code segment. […] Geos was originally intended to be converted to protected mode very early on […], with real mode only being a "legacy option" […] almost every single line of assembly code is ready for it […]
  • Paul, Matthias R. (2025-08-06). "Re: [fd-dev] ANNOUNCE: CuteMouse 2.0 alpha 1". freedos-dev. Archived from the original on 2025-08-06. Retrieved 2025-08-06. […] in case of such mangled pointers […] many years ago Axel and I were thinking about a way how to use *one* entry point into a driver for multiple interrupt vectors (as this would save us a lot of space for the multiple entry points and the more or less identical startup/exit framing code in all of them), and then switch to the different interrupt handlers internally. For example: 1234h:0000h […] 1233h:0010h […] 1232h:0020h […] 1231h:0030h […] 1230h:0040h […] all point to exactly the same entry point. If you hook INT 21h onto 1234h:0000h and INT 2Fh onto 1233h:0010h, and so on, they would all go through the same "loophole", but you would still be able to distinguish between them and branch into the different handlers internally. Think of a "compressed" entry point into a A20 stub for HMA loading. This works as long as no program starts doing segment:offset magics. […] Contrast this with the opposite approach to have multiple entry points (maybe even supporting IBM's Interrupt Sharing Protocol), which consumes much more memory if you hook many interrupts. […] We came to the result that this would most probably not be save in practise because you never know if other drivers normalize or denormalize pointers, for what reasons ever. […] (NB. Something similar to "fat pointers" specifically for Intel's real-mode segment:offset addressing on x86 processors, containing both a deliberately denormalized pointer to a shared code entry point and some info to still distinguish the different callers in the shared code. While, in an open system, pointer-normalizing 3rd-party instances (in other drivers or applications) cannot be ruled out completely on public interfaces, the scheme can be used safely on internal interfaces to avoid redundant entry code sequences.)
  • Bright, Walter (2025-08-06). "C's Biggest Mistake". Digital Mars. Archived from the original on 2025-08-06. Retrieved 2025-08-06. [1]
  • Holden, Daniel (2015). "A Fat Pointer Library". Cello: High Level C. Archived from the original on 2025-08-06. Retrieved 2025-08-06.
胆囊炎吃什么药好 相害是什么意思 老年人吃饭老是噎着是什么原因 受精卵着床是什么意思 尿白蛋白高是什么原因
吃什么补精子快 手脱皮擦什么药膏 梵蒂冈为什么没人敢打 7.30是什么星座 妇科病是什么
咳嗽能吃什么食物 肌酐低是什么原因 尿道痛什么原因 89年什么命 男人性功能不行是什么原因
痔疮是什么意思 脚底板疼痛是什么原因 加油站为什么不能打电话 茔是什么意思 新生儿屁多是什么原因
粉丝是什么意思hcv8jop8ns8r.cn 经期是什么意思aiwuzhiyu.com 6月是什么星座hcv8jop0ns9r.cn 看好你是什么意思hcv8jop2ns6r.cn 狗能吃什么wuhaiwuya.com
山的五行属什么hcv8jop8ns7r.cn 肺炎为什么要7到10天才能好xinjiangjialails.com 觉是什么偏旁hcv8jop7ns0r.cn 吃三七粉有什么效果hcv7jop6ns3r.cn 犹豫的反义词是什么hcv8jop9ns2r.cn
精神恍惚是什么意思zhongyiyatai.com 五二年属什么生肖hcv7jop7ns2r.cn 文联主席是什么级别hcv8jop3ns8r.cn 刘华强是什么电视剧hcv9jop6ns6r.cn 白带多用什么药效果好hcv7jop6ns2r.cn
十二指肠球炎吃什么药hcv7jop5ns2r.cn 什么老什么老hcv7jop6ns4r.cn 体脂率是什么意思hcv9jop2ns7r.cn 牙髓是什么hcv9jop4ns5r.cn 乌龟为什么会叫hcv8jop2ns7r.cn
百度